1

DreamMesh架构设计(2)-设计原则

 2 years ago
source link: https://skyao.io/post/201804-dreammesh-architecture-principle/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在展开详细的架构设计之前,先罗列一下Dream Mesh将在之后遵循的一些基本原则,以及这些原则背后的原因和期望的目标。

不敢立论说这些原则一定是对的,或者是最好的选择,只是从个人的感悟上出发,我更倾向于在这些原则的基础上架构整个Dream Mesh的体系。

原则:要服务不要类库

以注册中心和配置中心为例,通常的做法,是引入诸如zookeeper/consul/etcd等分布式一致性方案,然后编写代码调用其客户端API来操作数据。然后将编写的代码打包为类库,分发给使用者。典型如Java中就是提供一个依赖,然后可以导入一个或者若干个Jar。

这个方式非常的正统,由于是以类库的方式嵌入到应用中,实际运行时应用时直接和zookeeper/consul/etcd等服务器连接和访问。好处是设计上简单直白容易理解,执行效率较高。

但是,也存在一些问题:

  1. 即任何情况下需要升级类库,就必须重新分发,然后所有使用者都要重新打包上线。

  2. 引入大量依赖包

    由于是类库模式,需要引入依赖和递归依赖,导致应用的依赖数量大增,增加版本冲突等的可能性。

  3. 严重依赖客户端API

    类库是建立在客户端API上的,因此客户端API能做什么,有什么限制,有什么不足,都直接反应在类库上。

举例,在2016年我们开发Dolphin微服务框架时,当时选择consol,它的监听机制是基于HTTP long pull的,客户端引入了一大堆依赖,然后还非常不稳定,客户端版本升级也特别频繁。大受折磨,最后换etcd v3才得以解脱。

在Dream Mesh中,所有的功能模块都将以服务的方式提供,包括注册中心自己:

registry-center.jpg

配置中心:

config-center.jpg

应用在运行时,就不再依赖各种类库了,转而直接调用服务提供的接口:

application.jpg

原则:万物皆服务,服务皆注册

在Dream Mesh体系内,各个功能模块,都抽象为服务,然后在注册中心注册。

在使用时,也是尽量依赖服务发现机制。

好处是,所有模块都在注册中心有注册,则我们通过注册中心,就可以掌控整个体系。至少,有什么东西,部署在哪里就可以有一个统一而完备的记录。

这应该算是一个目前比较主流的做法,只是Dream Mesh中会做的比较彻底,比较绝。

原则:内部通讯走gRPC

Dream Mesh体系中的内部通讯,尽可能的选择使用gRPC作为通讯机制。

主要理由如下:

  1. gRPC有完备的跨语言/跨平台的支持,也已经坐稳了下一代RPC的位置,日渐主流
  2. gRPC基于HTTP/2,可以提供远比HTTP/1.1强大的特性,最关键的,监听实现起来舒服多了
  3. gRPC提供的双向stream,在后面的设计中会大量使用,成为很多模块的主要工作模式
  4. gRPC单连接的工作模式,不需要连接池,简化了客户端实现。

和用在服务间通讯时,需要权衡REST和gRPC相比,在内部通讯中,有些常见的制约和不足不再明显:

  • 开发和使用方式:内部通讯都是直接提供客户端依赖(注:这个客户端已经简化到只是完成访问服务接口),使用者完全不涉及到gRPC的开发和直接使用,对使用者其实是透明的。
  • 不是文本模式:对于内部通讯,基本不存在需要抓包看报文类的操作,我们会通过收发请求前后的日志来提供足够的debug信息。

原则:优先提供直接语义的专用接口

所谓"直接语义",指不需要考虑通用性,直接针对某个意图特别明确的操作,提供和这个操作的意图明确匹配的业务语义。

典型如服务发现,正统的接口设计,会提供若干个查询接口,然后组合监听/通知的接口,一起为客户端提供完备而有弹性的选择。

但是对于大多数情况的客户端,其业务语义往往非常的直白而集中:我要做服务B的服务发现,现在给我服务B的实例列表,然后如果有变动请及时通知我。中间我们要保持网络连接,发心跳包,顺便实现简单的健康检查。

在有gRPC的双向stream支持的情况下,我们可以将类似的场景直接封装为一个"直接语义"的接口,一次性的解决客户端的各种需求。

当然,这个"直接语义"的接口是额外提供的,虽然我们推荐尽量使用这个接口,但是普通的接口也是会一并提供。

在后面注册中心和配置中心的设计中,我们将广泛应用这个原则。

讨论和反馈

TBD:等收集后整理更新

有兴趣的朋友,请联系我的微信,加入Dream Mesh内部讨论群。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK