# 微服务设计
- 微服务的好处
- 架构
- 建模服务
- 集成
- 分解
1. 微服务的好处
- 技术的异构性,不同的服务可以用不同的语言实现,甚至同一个服务用不同的语言实现。
- 弹性,也是非常重要的优点,哪个服务需要的资源多,多部署几个就好了,而不是把整个项目都部署好几套。
- 拓展,单个服务间是独立的,所以拓展是不应该影响之前的服务,易于拓展
- 简化部署,因为服务小,同弹性的优点相同
- 可组合性
- 相对大型项目,改代码时简单
架构
面向服务的架构(SOA),这是一种设计方法,它所设计的系统包含多个服务,通过相互配合最终提供一系列功能。 每个服务独立运行,通过网络调用,而不是进程之间。
这种设计我们会有上述的好处,但也会面临各种问题!在网络中,使用什么通信协议、服务的粒度的大小判定、中间件的选择。然后再等到动手去做时,会出现事务怎么一致啊,数据库怎么拆啊,以前的联查怎么办啊等等一系列的问题!
建模服务
建模服务是书中的第三章,大概讲的是建模服务的原则,总结6个字
松耦合,高内聚 遵循这个6个字,让做的微服务能达到:
- 修改一个服务模块时不需要修改另一个
- 修改某一类功能时只修改一处就可以
在书中我认识了个新名词:洋葱架构 ——”因为它有很多层,而 且 当 纵 切 这 些 层 次 时, 我 只 想 哭。“ 以我目前只有2年的工作经验,我还没碰见想哭的。。。但以此自警,不要写出让人哭的东西!
集成
服务拆分成功了,但怎么集成?
好的集成:
- 避免破坏性修改
- API的技术无关性!
- 服务易于消费方使用
- 隐藏内部细节:消费方如果需要了解更多服务方细节的话,那么就代表着消费方与服务方会发生过多的耦合
对于上述的第二点,我们使用的是dubbo,所以API就是接口,所以我们的微服务并没有完全独立!当当开源的dubbox可以提供http协议的接口
还有个数据共享的问题
- 例如未拆分前的静态变量如何在多个子服务间共享?每个微服务都要copy个代码的话修改会不会太麻烦?或者有个服务专门提供这个数据,如放到数据库中
- 数据库有无拆分的必要?很有必要,微服务是独立的服务,如果改动该微服务的数据库需要重启等事件发生时,那么和它共用数据库的服务可能就要宕了!
编排和协同
这是个客户下单过程
- 编排:客户服务为中心,调用其他服务
- 协同:需要额外服务做监测
协同降低耦合,需要额外的监测服务。相对编排,改动时工作量少!个人也喜欢协同模式,这让我想起了java中的观察者模式,非常方便的开发方法~
对于相对小点的项目,也许‘编排’开发起来更简单快捷
REST 和 RPC的对比
REST基于http相对低延迟的服务不如RPC,尤其是在服务端与服务端之间,但RPC要客户端和服务端代码共享,也因为代码共享,序列化和反序列化相对简单。
Don't Repeat Yourself.
重复的代码导致你修改时可能会漏掉某个地方。所以强制性要求,是有道理的,但是,微服务共享代码时就会导致耦合现象!
客户端库:针对上述问题,网上有很多SDK,例如百度的云存储等SDK,实际上,这些sdk可能来自社区,例如阿里的sdk很多都是通过osc悬赏开发的,他们统一API,但具体客户端实现和升级交给客户。
接口数据的原则——宽进严出
对读取的数据要有容错性读取,即对进来的数据,只找自己需要的,不需要的尽量不去管。
该原则可以帮助我们在服务方发生变化时,减少消费方修改。
分解
考虑完集成我们就开始分解吧!
不要为了拆分而去拆分,是为了哪部分代码抽取出去后收益最大!
拆分所得到的好处:
- 速度提升,例如某个模块需要大量修改时,拆分后只修改一个子项目,那么后期开发速度会很快!
- 团队结构,分工更加明显
- 安全性
各个模块分离开,安全就能提高吗?
- 技术
目前在技术上最大的帮助解决了大型项依赖杂乱!
数据库的分离
- 打破外键关系,因服务拆分后数据库分离后,外键关系也因此打破,导致有些数据查询需要通过API实现,尽管性能会有所降低,但慢也能接受。
- 共享的静态数据
- 要确保一致性——导出copy 代码
- 做成配置文件——从代码中提取出来改到配置文件
- 最复杂——单独提供服务
- 共享的数据——提供API接口
- 共享的表——拆分
分离服务的步骤:
先拆分数据库,再拆服务:因事务的关系,当服务未拆分时,还能保持事务的一致性。当数据库分离的结果满意后再实施下一步
事务!!!
- 最终一致性:协同操作的服务,其中一个服务出错,可以重试,最后一致即可!
- 补偿事务
- 分布式事务
需要保持一致性的场景的服务,就尽量在一起,如果避免不了也要避免使用纯技术手段去解决,而是显式的创建一个概念去表达这个事务。在此之上去补偿或最终一致事务