Rails Rails 微服务初探

rocLv · 2020年12月29日 · 最后由 yingce 回复于 2021年01月06日 · 2747 次阅读

微服务架构组成

一套微服务架构一般由以下几个部分组成:

  • 服务注册与发现中心
  • 配置中心
  • 服务网关
  • 服务限流和熔断
  • 服务路由
  • 微服务跟踪等

alt 微服务架构图

携程的Apollo是基于 Eureka 构建的,提供了 REST API,这为 Raills 项目使用 Apollo 提供了可能性。

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

其实 Apollo 实现了两件事情,一是服务注册与发现,二是配置中心。服务注册与发现是在 Eureka 上面增加了一层 Proxy,提供了一套 REST API 接口。

服务网关位于业务逻辑层之上,处理业务逻辑之外的一些事务,比如鉴权、Load Balance 等,根据业务需要其实最好的是自行开发。

服务限流和熔断貌似没有合适的选择。如果自行开发的话可以放在网关层。Rails 也可以写一些中间件来完成。

微服务跟踪可以采用zipkin.

以上这些或多或少的貌似都有可选择的方案,有些自己实现起来也并不复杂。但是微服务引入的复杂度还在于分布式事务的提交和回滚等,这方面推荐微服务架构设计模式 这本书。

由于微服务架构的特性,所以无法同时保证 CAP(一致性、可用性、分区容错性),所以需要根据业务选择相应的设计模型,比如 CP 或 AP 模型。金融类行业多选择 CP 模型,聊天类的这种就可以选择 AP 模型。

当然,对于微服务的知识体系来说,这里提到的只是冰山一角。在做具体架构设计的时候,要多考虑一下选择的工具是否满足整体架构的模型。比如说整体业务是 CP 模型,那么如果选择 Redis 做分布式锁的时候就不太恰当。因为 Redis 分布式架构采用的是主从结构,是 AP 模型,所以就不太合适。此时应该选择 etcd。

总之,相对于 Java 语言的生态来说,Ruby 语言的微服务生态貌似没那么好(其实是没找到,大家知道的可以补充一下)。

一切架构都从需求出发,,,,一个人维护几个微服务的时候你就抓瞎了。

pynix 回复

符合需求的前提下,越简单的实现越好

PS 感觉 Rails 还是搞单体香

pynix 回复

咱说的不是一回事😂

pynix 回复

一个人维护多个微服务不是问题,问题取决于生态。

之前写 JAVA spring boot 微服务,一个大项目(按团队/业务部门)下有 N 个 module,每个 module 容器化独立部署微服务。

module 之间通过 RPC 调用,但因为 controller 遵循接口的方式去实现。用 IDE,RPC 调用端可以直接跳转到代码的实现,进行修改。

体验就是,跟正常的单体应用开发区别不是很大,微服务只是一种解耦的方式而已,好处就是便于维护(解耦的本质),写的也很爽。

但是 ruby 做微服务,如果在 N 个项目跳来跳去的,简直是一种灾难。

需要做到屏蔽底层细节,和直接调用函数那么方便才行。

要是我,估计在数据一致性上抓瞎。。。

CAP 是存储要考虑的,除非这个服务没办法搞成无状态的才需要考虑。而且几个节点 partion 的可能很小,可以不考虑。

pynix 回复

debug 才是麻烦的事情

一致性,有些时候也没那么重要,可以牺牲掉换新能,或者业务层处理一下。

很关键的地方,再根据具体情况处理。

ETCD 的一致性保证有点迷,读的时候是有可能读到旧数据的。

ttps://etcd.io/docs/v3.3.12/learning/api_guarantees/

然后,network partition 的时候,有说能读,有说不能读的,https://stackoverflow.com/a/28927474/2477886

ETCD 基于 Raft,但没完全用 Raft,Raft 的 request 都是要经过 master,这样的话,没办法横向扩展,ETCD 应该是没有完全用。。。具体怎么用的,还得看代码。。

pynix 回复

除了有网络 IO,用起来就跟普通函数调用没啥区别。java 强类型的,屏蔽底层细节之后,RPC 调用之后返回值是一个具体的对象(但是本质上是个接口,一堆 getter 方法)。

yfractal 回复

服务无状态化并不是说服务不会修改数据库内容,而是服务本身不储存状态。比如 session 等。

rocLv 回复

恩,是的,无状态是说服务本身没有状态。

如果是无状态的服务,比如 API 服务,一致性一般是由后面存储保证。

一般 API 服务,可以不去考虑 CAP。存储服务(包括有状态的服务),比如 ETCD,才需要考虑 network partition 的时候,是否可读可写之类的。

一致性一般是由后面存储保证

不过也有特殊情况,GFS 存储就不保证一致性,由 lib 来处理。riak_pg(pub/sub),network partition 的时候可用,连回来的时候解决冲突。

tinyfeng 回复

但是 ruby 做微服务,如果在 N 个项目跳来跳去的,简直是一种灾难。

这个应该搞 monorepo,放一个 git repo 里

tinyfeng 回复

一个人维护多个微服务不是问题,问题取决于生态。

一个人维护还简单

人多里容易成焦油坑,我现在积累了很多反模式的经验😄

lidashuang 回复

这个应该搞 monorepo,放一个 git repo 里

即使是这样,ruby 的特性也决定了,你并不能直接跳转到调用服务的定义处,只能通过 复制 -> 搜索 -> 粘贴 -> 选择

rocLv 回复

我有一点疑问

“用 IDE,RPC 调用端可以直接跳转到代码的实现,进行修改。 体验就是,跟正常的单体应用开发区别不是很大,微服务只是一种解耦的方式而已,好处就是便于维护(解耦的本质),写的也很爽。”

既然已经解耦了 各个团队负责各自的 module 为啥你能去改别人的 那不还是没解耦么 单纯的代码解耦不能叫项目解耦呀

zj0713001 回复

放在一个 repo 里方便开发测试,一般来说不会动别人负责的模块。现实中的例子就是各个部门在一栋楼工作,方便沟通协作,但是你不会去干跨部门的活

rocLv 回复

那就对了 这样确实友好很多

服务注册发现 + 熔断限流 + 负载均衡 可以用 airbnb 的 smartstack,可以集成 zookeeper 或者 etcd,独立进程不用修改应用,也有类似配置中心的作用。或者直接上 k8s + istio

微服务追逐,用 elasticapm,可达到同样作用,感觉比 zipkin 好用,ruby client 集成也方便,还省了用 newrelic 收费版

zhchsf 回复

k8s istio 普通团队 hold 不住啊

微服务引入了太多的复杂度

lidashuang 回复

都微服务了,肯定不是普通团队了

现在微服务越来越像标准了,标准超过实践了,对成熟的微服务框架挺好的。
Rails 做也不是不行,我之前也考虑过搞一个中间件,但是发现除了微服务本身治理还有很多东西需要做出统一:同步接口用什么写,异步接口怎么写,队列怎么做等 我觉得都挺不统一的。约束性太高了,感觉这个约束不是“约定”。到后来搞得可能就是自己写的爽 其他人就不一定了。😂

需要 登录 后方可回复, 如果你还没有账号请 注册新账号