写点什么

架构师训练营 1 期 -- 第十周总结

用户头像
曾彪彪
关注
发布于: 2020 年 11 月 25 日

巨无霸架构产生的问题:

  • 部署,编译困难

  • 版本管控困难

  • 团队协作困难

  • 数据库连接池耗尽

  • 耦合性高,系统之间互相影响,一个模块出问题(OOM),导致其它模块受牵连。


在微服务之前,也曾出现过 Web Service,使用一个注册中心,服务提供方注册服务,服务调用方发现服务并调用。这是注册发现机制的前身,虽然 Web Service 没有火起来,但是后来的微服务框架都采用了它的思想。


微服务框架需要考虑的技术功能点包括:

负载均衡,微服务框架应该实现负载均衡策略,调用方不用自己去实现它。

失效转移,一点服务调用失败,微服务应该能切换到其它服务进行调用。

高效的远程通信,调高性能,节省开销。

无侵入,尽量降低对代码的侵入,不影响业务开发。

服务版本管控,多版本同时存在,不同的客户端或者不同版本的客户端可以调用不同的版本。


Service Mesh 是一种服务网格技术,在微服务的基础上,再抽象出一层服务调用层,应用程序只需要与 Service Mesh 通信,而不用去关注服务的注册与发现。Service Mesh 在负载的应用系统中会带来一些优势,如果服务调用简单,还是需要慎重考虑。


微服务落地需要遵守的一些原则:

  • 业务先行,先理清业务关系,确立好模块的职责,再考虑是否上微服务。如果要上微服务,也需要明确上微服务的目的是什么。

  • 命令去查询职责隔离(CQRS),查询服务只提供查询功能,命令服务只提供数据操作功能。这样可以针对不同的服务做性能优化,同时也可以减少出错的可能。

  • 时间溯源,按照时间顺序记录所有的数据操作日志,可以清楚的复现问题,也可以做事件的回滚。

  • 需要设计好断路器,当部分服务不稳定时,断路器打开,减少对不稳定服务的调用,有利于提高整个服务的稳定性。

  • 上游服务的调用超时时间应该大于下游服务的超时时间,如果上游服务超时时间小于下游服务超时时间,可能会出现大量的调用超时。

  • 在技术的道路上,需要遵守的一个重要原则时,需求最大原则,应该从需求考虑,能带来什么价值,我们的原则是什么,然后再去实践,最后是选择合适的技术或工具。(Need->Value->Principle->Practise->Tools)。


在微服务系统中,几乎所有的请求都经过网关,网关的作用可以有很多,但都是一些非业务的功能,如鉴权,限流,降级,数据整合,负载均衡等等。在网关中,一般使用管道方式处理请求,也就是我们常见的责任链模式,这样可以比较灵活的添加或重组功能。

Flower 中的异步网关是使用了 Server3 中的异步请求功能,当前线程关闭后,HTTP 连接不关闭,其它线程依然可以通过 socket 发送数据给客户端。


对于要实现开放平台网关的服务,可以使用 Oauth2.0 技术。Oauth2.0 包含了资源所有者,资源提供方,客户端,以及授权中心。一个典型的基于 Code 验证模式的授权流程如下(以微信登录为例):

  1. 第三方应用提供微信登录连接。

  2. 用户点击微信登录,跳转到微信授权服务器提供的微信登录页。

  3. 用户扫码登录,通常会把用户 ID 和 redirectUrl 带过去。

  4. 扫码验证通过后,表明用户同意授权,则返回 Code。

  5. 然后跳转到 redirect,会带上用户 ID 和授权 Code。

  6. 第三方应用拿到用户 ID 和授权 Code,再向微信授权服务器发起请求,获取 token。

  7. 授权服务器验证,通过后返回 token。

  8. 第三方应用携带 token 访问资源服务器,就是微信服务器,获取相关资源,如头像,好友列表等。


在微服务设计中,与微服务技术或框架相比,更重要的是对业务的数据服务模块的拆分,可用到的一些方法包括 DDD。


与领域模型对应的是事务脚本,事务脚本的设计方式是将应用系统分成 controller,service 和 dao 等,大量的业务逻辑处理放在 service 中,而 service 和 dao 这些类,一般也不包含数据,只有方法,所以也成为贫血模型。与之对应的领域模型是指面向现实时间的模型编程,一个对象既包含状态数据,又包含与之对应的业务处理的方法,这种设计也被成为充血模型。


领域是一个组织所有做的所有事情,一个领域的范围通常比较大,可以对其进行拆分,划分成多个子域,与之相关的另一个概念是界限上下文,它限定了子域的边界,一般来讲,子域是逻辑上的划分,界限上下文是物理上的划分。域,子域,界限上下文以及界限上下文图,都是 DDD 中战略上的设计。

领域模型对象也叫实体,一般包含各种属性和相关计算的逻辑。与实体对应的是值对象,实体的状态是可以改变的,值对象的属性通常是不变的。而聚合是一个关联对象的集合,一个微服务中可以包含一个或多个聚合。 实体,值对象,聚合,聚合根是 DDD 中的战术设计。


软件设计是一项需要长时间积累的工作,体现了一个工程师的核心竞争力。

在软件设计过程中,组件需要遵守以下高类聚原则:

  • 复用发布等同原则,你想要用户已怎样的粒度使用你的组件或服务,那你就用这样的粒度去设计它。个人觉得这条原则非常有用,微服务的粒度是很难把控的,遵守这个原则就不会困惑。另外在版本发布时,版本号应该使用主版本.次版本号.修订号的格式。

  • 共同封闭原则,就是那些需要共同修改的类,应该放在同一个组件中。

  • 共同复用原则,组件不应该强迫用户依赖他们不需要的类。

同时,组件设计需要遵守以下低耦合原则:

  • 无循环依赖,直接和间接的循环依赖都是不好的,容易影响文件的稳定和问题的排查。

  • 稳定依赖原则,不稳定的组件应该依赖稳定的组件。

  • 稳定抽象原则,组件的抽象化程度,应当与其稳定性一致。这给我们的指导性意义是,如果一个组件它是不稳定的,那么可以设计出一组接口,把这组接口封装在一个专门的组件中。JDBC 就是一个稳定抽象的例子,其具体实现是不稳定的,而接口时稳定的。

组件的高类聚低耦合原则,只是给我们在组件设计时提供一些指导思想,通常还需要结合实际的业务场景或其它因素来进行设计。


在做具体的软件设计时,架构师应该更多的把精力放在问题本身,对其进行分析,整理,归类,划分出系统边界,进而进行软件设计。而不应该直接说我们用某个技术来解决某个问题。


用户头像

曾彪彪

关注

还未添加个人签名 2019.03.23 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营 1 期 -- 第十周总结