Rails Rails 微服务初探

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

微服务架构组成

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

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

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 做也不是不行,我之前也考虑过搞一个中间件,但是发现除了微服务本身治理还有很多东西需要做出统一:同步接口用什么写,异步接口怎么写,队列怎么做等 我觉得都挺不统一的。约束性太高了,感觉这个约束不是“约定”。到后来搞得可能就是自己写的爽 其他人就不一定了。😂

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