Microservice Architecture
Why Microservice
- Heterogenious technical stack:
支持多重技术栈,由于HTTP协议被多种编程语言支持,微服务可以用多种语言实现。 - Robustness:整个App mesh网络不会因为单一的微服务的奔溃而停止工作。
- Extensions:可以针对单一微服务进行扩展。
- Simple deployment:微服务可以进行独立部署,不需要因为单一服务升级而多次部署。
- Efficiency:微服务小团队开发高效敏捷。
- More client support:多种前端客户端支持,可以重复利用同一个微服务后端网络。
- Migration:基于单一微服务迁移的整体升级,阻碍更小。
What is Microservice
微服务就是一些协同工作的小而自治的服务。
How to architect Microservices
微服务特点
Loose coupling松耦合
High Cohesion高内聚
上下文边界确定
业务或者职能的界限,往往也可以作为微服务架构中的服务边界。不同的业务只能之间的内部细节并不需要相互知晓。同一个事件,在不同的业务职能会有不同的体现,但是在内部细节上却没有相互交叉。
共享和隐藏模型设计
限界上下文的确立,能够帮助确立共享模块,对于处于两个上下文边界上需要共同的消息,可以确立一个共享模块,专门进行信息共享。同时,对于上下文内部的逻辑,也能进行对应的逻辑模块设计,从而完成对于整个上下文的设计。
切勿过早划分
对于一些过早划分的业务产品,警惕由于后期需求用例改变造成多个上下文之间的重叠。比较推荐的是先进行单体设计,不进行划分,在服务稳定之后再进行划分设计迁移,基于以有代码进行划分,比从头开始构建微服务简单得多。
逐步划分上下文
不断对上下文的界限进行迭代,从复杂的共享模型中慢慢抽出简单的共享模型,将嵌套的模块逐步上升到顶层模型,对其中某些紧密关联模型进行共享。当然,模型共享的粒度取决于代码是分开维护还是集中维护,如果是集中维护也未尝不可进行嵌套模型共享。
微服务的集成
微服务之间的通信机制,可以成为微服务的集成。微服务间的API相互调用设计需要注意一下几个方面:
为用户创建接口
用户上下文会触发一定特定的流程。
共享数据库
数据库是多个微服务共享的,因为每个微服务都可能对同一个数据库进行修改。
同步与异步通信模式
两种不同的通信模式中,同步模式会阻塞线程,而异步模式是基于事件响应请求的,能提降低耦合性,提高吞吐量。
编排与协同
编排和协同是两种管理流程的架构风格。(同步)编排是通过一个中心执行者将每一步的步骤执行,知道获取最终的结果。(异步)协同则是以事件为机制进行执行,执行单元会订阅事件,API调用会触发一个事件,事件订阅者则会自动执行响应的流程。后者会需要监控服务,监控结果要映射到流程中,troubleshooting难度增加,这是一个难题。ATOM是一个符合REST规范的协议可以通过它提供资源feed的发布服务,客户端可以消费该信息。
RPC与REST
远程调用允许进行本地调用,事实上是由某个远程服务器产生。RPC会有一定的技术耦合要求。protocol buffers, Thrift是比较推荐的RPC框架。REST则是RPC的一个替代方案。通过URI对客户端与服务器进行了松耦合。
Json与XML
JSON与XML都是一种有效的数据序列化格式,前者更加流行XML对超媒体控制更加好。
API重定向
API的重定向常常发生在多个API版本共存的时候,当老版本的API准备deco时,需要绞杀者模式将旧的API拦截,选择是否替换成新版本的实现。当旧版本的访问完全消失时,再删除旧的API。
拆分成微服务
- 寻找独立的上下文边界——接缝
- 拆分数据库表格的混合加载功能,放弃直接利用数据库命令访问上下文边界间的外键,改为由代码(微服务服务API)
- 共享的静态数据改由配置维护关联。
- 针对共享数据,建立合适的领域进行关联,例如代码中建立客户关系,来维护财务——客户——仓库关系。
- 共享表格,对于有大量列信息的表格,可以根据上下文边界将表格拆分成两个。
- 自数据库开始进行代码重构。
- 事务的边界重构,对于多表的修改操作,需要协同处理错误,或者利用分布式事务处理工具代为管理事务。
- 拆分后的数据库在制作报表时会出现问题,因为不再能用sql语言进行表格操作。解决方法可以是主动定期导出表格合并,或者基于修改时间订阅导出行为。
部署微服务
- 准备CI系统,流水线,自动化流程
- Paas,Docker打包部署
测试
- 单元测试
- 服务测试(mock/打桩)
- E2E测试 —— 消费者驱动的测试
- 上线 —— 金丝雀发布法
监控
微服务的监控难度高于单一服务器应用。微服务包含多个服务,而每个服务的实例个数不等。关联标识可以帮忙关联同一个事件服务调用的日志,采用统一标准化的格式能够更快的辅助错误定位。
监控的内容包括CPU,响应时间,以及合理的语义监控(合成事务监控)。
微服务安全
- 身份验证和授权
身份雅正确认了登录者的身份。授权机制能够确定登录者可以访问和进行的操作。常见的单点登录(Single Sign-On),企业级标准为SAML和OpenID Connect,前者基于SOAP标准,后者基于OAuth2.0. 身份提供者可以是外部系统或者内部目录服务,如LDAP/AD等。
微服务的身份认证和授权部分可以依托于网关,网关可以作为认证代理,通过网管认证的所有查询和操作都可以发送到微服务集群任意一个实例中处理。微服务内部可以决定身份可以授权的操作。
- 服务间的身份验证和授权
服务之间的身份验证是指微服务的各个服务之间的身份验证和授权,一般来说有如下几种方式管理:
- 在微服务边界内允许一切
- HTTP(S)基本身份验证(HTTP明文传输认证信息,如果基于SSL认证则需要管理多台服务器之间的自签发证书。)
- 使用SAML或OpenID Connect认证授权,可以有效的避免中间人攻击,这样每个服务也需要一个身份。
- 客户端证书(采用客户端X.509证书,通过TLS层协议对服务器验证进行保证。)
- HMAC(Hash-based Message Authentication Code,请求主题和私有密钥一起被哈希处理后进行发送,服务器使用请求主题和自己私钥副本重建哈希值。如果匹配则接收,防止的中间人攻击。)
- JWT(JSON Web Token,JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户。当用户与服务器通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识用户。为了防止用户篡改数据,服务器将在生成对象时添加签名。)
- API密钥(API密钥是给予某种形式的秘密令牌的名称,该秘密令牌与Web服务(或类似)请求一起提交以便识别请求的来源。密钥可以包括在请求内容的一些摘要中,以进一步验证原点并防止篡改值。)
- 数据加密(现存多种算法进行数据加密,密钥可以通过加盐哈希保护)
- 深度防御
- 防火墙
- 日志
- 入侵监测
- 网络隔离
- 操作系统安全
- OWASP标准(Open Web Application Security Project开放式Web应用程序安全项目,https://www.owasp.org)
系统设计与组织架构
公司团队的组织架构会影响系统设计。
单地域的团队拥有更加好的灵活性和效率,因此对于异地团队最好的办法是想办法合理拆分,让不同的团队负责不同的松耦合模块。
每个团队需要负责对服务的需求,更改,构建,部署到运维,自治的团队能够很好的激励团队的效率。
小团队规模,少于10个人的团队能够对其所负责的系统整个生命周期负责,技术选择和实现上具有灵活性。当然这个对服务的高效构建部署效率很高,比如利用云服务的Infra来轻松构建CI/CD流程。
规模化微服务
允许故障无处不在,故障永远会在意想不到的时候发生,所以微服务本身需要能够允许故障出现,硬件上也不用为避免故障作特殊设计。
服务平行扩容阈值控制,需要参考一些系统参数,响应时间/延迟,可用性,数据持久性(丢包率)。
当故障出现时,适当的服务功能降级,允许应用能够在其他方面能够正确运行而不是直接返回错误界面。
微服务延迟的影响控制,通常会导致worker线程池的阻塞队列超长,最终线程池没有可用的线程而宕机。合理设置线程池的舱壁bulkhead,在舱位线程用尽后断路该服务,避免因为单个服务的延迟影响导致所有的线程都阻塞于同一个服务。
数据库扩展,当数据库需要服务于高吞吐量服务时,可以通过数据库副本,RDBMS系统,扩展写操作,独立CQRS读写分离系统,等多种方式扩展。
缓存可以优化重复请求,氛围哭护短、代理和服务器端缓存。
自动伸缩,当云管理能够强大到自动调整微服务实例个数,就可以基于当前流量进行自动调整。
CAP定理(一致性consistency、可用性availability和分区容忍性partition tolerance)是分布式系统中需要控制好的三个平衡。
服务发现,可以通过DNS服务器进行关联,负载均衡服务器将查询分发到不同的IP服务器上。
动态服务注册,新加入的微服务实例的IP应用信息需要能共享给其他服务,Zookeeper,consul和Eureka等服务可以管理配置管理和服务发现。
文档服务,为API构建合适的文档,Swagger可以很好的自动生成API文档,HAL和HAL浏览器也可以客户端逐步探索API。
自描述系统(UDDI Universal Description Discovery and Integration通用描述发现与集成服务),这个标准能帮助了解哪些服务正在运行。