二、微服务相关技术介绍
在本篇文章中将对微服务体系结构中所常用的技术或框架进行介绍,本文主要介绍的是基于事件总线实现的微服务体系结构。
1. 微服务
A. 什么是微服务
顾名思义,微服务体系结构是一种将服务器应用程序生成为一组小型服务的方法。 这意味着微服务体系结构主要面向后端,虽然该方法也会用于前端。 每个服务都在自己的进程中运行,并使用 HTTP/HTTPS、WebSocket等协议与其他进程进行通信。每个微服务在特定的上下文边界内实现特定的端到端域或业务功能,每个微服务都必须自主开发,并且可以独立部署。 最后,每个微服务都应拥有其自己的相关域数据模型和域逻辑(主权和分散式数据管理),并且可以基于不同的数据存储技术(SQL、NoSQL)和不同的编程语言。
B. 为何选择微服务体系结构?
简而言之,它提供了长期的灵活性。 通过允许基于许多独立的可部署服务(每个服务都具有粒度和自主生命周期)创建应用程序,微服务在复杂、大型和高度可缩放的系统中支持更好的可维护性。
微服务的另外一大优势是,可以独立横向扩展。 可以横向扩展特定的微服务,而无需将单个整体应用程序作为一个单位扩展。 这样便可单独缩放需要更多处理能力或网络带宽以支撑需求的功能区域,而不用横向扩展应用程序中不需要缩放的其他区域。 这意味着节省成本,因为所需硬件更少。
2. Docker
A. 什么是Docker
Docker相信大家都不陌生了,他是软件容器化的一种解决方案,用于将应用程序自动部署为可在云或本地运行的便携式独立容器。Docker就像一辆卡车,不,应该像一辆货运火车,它运载多个集装箱而不管集装箱里面是什么。又有些类似OOP里面的封装一样,只关注如何使用,不必关注具体实现。Docker像虚拟机一样,你可以在上面运行几乎所有的软件镜像。
B. 为什么使用Docker
Docker类似虚拟机但不同于虚拟机,对于 Docker,主机服务器仅有基础结构和 OS,在其顶部是容器引擎,它将容器隔离,但共享基础 OS 服务。
由于容器所需的资源要少得多(例如,它们不需要一个完整的 OS),所以它们易于部署且可快速启动。 这使你能够具有更高的密度,也就是说,这允许你在同一硬件单元上运行更多服务,从而降低了成本。
Docker 容器可以在任意位置运行:在客户数据中心本地、在外部服务提供商或在各种云中。 Docker 映像容器可以在 Linux 和 Windows 上本机运行。 但是,Windows 映像仅能在 Windows 主机上运行。
基于容器的解决方案对于节约成本大有裨益,因为它们可以帮助减少由于在生产环境中依赖关系异常而导致的部署问题。 容器显著改善了 DevOps 和生产操作。
C. 开发基于Docker容器的应用程序
- 步骤一 创建应用程序
- 步骤二 创建DockerFile
- 步骤三 根据DockerFile创建镜像并将应用或服务嵌入其中
- 步骤四 生成多容器应用程序时可以在docker-compose.yml定义服务
 docker-compose.yml 可以用来定义程序的依赖服务,每一个服务都将部署成一个容器,因此每个服务都需要一个Docker镜像。
- 步骤五 生成并运行Docker应用程序
3. 事件总线 EventBus
事件总线可实现发布/订阅式通信,无需组件之间相互显式识别。事件总线技术可以用于微服务之间基于事件的通信。例如下单之后生成订单并减库存,便可以在下单操作时订单服务发布事件库存服务订阅事件。
分布式系统如何实现实现总线呢?可以采用RabbitMQ 创建自定义事件总线,使用RabbitMQ 充当消息发布服务器和订阅者之间的中介,处理分发。
RabbitMQ本身就有可靠性可持久化的支持,即便是RabbitMQ挂掉,在下次重启时消息依然能够恢复。需要注意的是消息的及时性和死信问题。
4. 网关
A. 网关是干嘛的?
顾名思义,网关就是网上的一道关卡(doge)。网关是外网和应用程序之间的一道桥梁,它决定请求通过怎样的路径可以访问资源,哪些请求不能访问资源,它可以在突发情况下保护系统,它也可以在故障发生时进行故障转移。
B. 有哪些网关框架(产品)
对于.net系而言,网关有两个比较好的选择  Envoy 和 Ocelot,Envoy的特点是对 WebSocket 协议的内置支持,对于采用gRPC(gRPC Remote Procedure Calls,Google 发起的一个开源远程调用框架)实现服务间通信而言非常方便。而Ocelot在.netcore界也是鼎鼎大名,在搜索引擎一搜.netCore网关出来的数据基本都是Ocelot。
5.领域驱动设计 DDD
恩,DDD这东西吧,因为涉及领域的划分,于是千人千面,可能一百个哈姆雷特里面就有一百个莎士比亚呢(doge)。so,没必要盲目追求DDD,一般来说DDD适合二开而不太适合敏捷型项目。
那么,我的理解是什么呢?我觉得应该回到面向对象的本质上来,我们目前创建的实体其实不算完整对象,对象是具有属性和行为的,而绝大部分实体是只有属性的,这种实体模型通常被称为贫血模型。在老式分层设计中,对象的行为通常分布在BLL,DAL层中实现。在当下IOC盛行的时代,行为在Interface定义,在Interface的Implementation中实现。DDD讲究的是领域性,因此模型应当自己具有行为,而不是经由其他模块代理。通常的,我们将具有行为的模型叫做充血模型。
* 个人见解,不代表DDD的真实定义
6. CQRS
CQRS(Command Query Responsibility Segregation)即读写分离也叫做命令查询职责分离,是一种分离数据读取与写入模型的体系结构模式。基本思想是可以将系统操作划分为两个类型:
- 查询。这些操作只返回结果,不改变系统的状态,且没有副作用。
- 命令。这些命令会更改系统状态。
 CQRS 的分离操作通过将查询操作分到一层中而将命令分到另一层中来实现。 每一层都有自己的数据模型或者数据库,并且使用自己的模式和技术组合来构建。
CQRS解决了什么问题
或者说,我们为什么要用CQRS?
- 提升并发能力
- 降低业务复杂性
CQRS缺点
- 事务
 因为将原本的单一操作变成了读写分离,那么数据的CAP将会受到挑战。
- 基础设施薄弱
 目前没有相对成熟易用的CQRS框架,很多时候不得不自己去实现。
7.NoSQL
非关系型数据库,算是微服务的标配吧。常见的有MongoDB、Azure Cosmos DB、cassandra等。使用NoSQL数据库的一项优势是实体更加非规范化,所以不用设置表映射。 域模型较使用关系数据库时更加灵活。区别于关系型数据库,NoSQL数据库它们不保证关系数据的ACID特性,这恰好迎合了微服务的特点。在微服务中,我们总是无法保证CAP完全满足的,通常的做法是满足AP牺牲C,然后再通过最终一致性对C进行补偿。
8.故障转移及处理
这里要推荐一个.Net库Polly ,Polly提供恢复能力和瞬态故障处理功能。 通过应用 Polly 策略可实现如重试、断路器、舱壁隔离、超时和回退这些功能。
需要注意的是:
在高并发率、高可伸缩性和高争用的情况下,常规重试策略可能会对系统产生影响。 在部分运行中断时,可能会有许多客户端同时发出相似的重试操作,从而形成操作高峰,为避免这种情况,一个好办法是向重试算法或策略中添加抖动策略。 该策略可以改进端到端系统的整体性能。
9. 运行状态监控
运行状况监视可以获取有关容器和微服务状态的近实时信息。 运行状况对于微服务操作的多个方面至关重要,并且在业务流程协调程序分阶段执行部分应用程序升级时尤为重要。
通常,基于微服务的应用程序借助检测信号或运行状况检查,使性能监视器、日程安排和业务流程协调程序得以对大量服务进行跟踪监测。 如果服务无法按需或按计划发送某种表示“我处于活动状态”的信号,那么部署更新时,应用程序可能面临风险,或者它可能太晚才发现故障,并且无法阻止可能会导致重大故障的级联故障。
在典型模型中,服务发送有关其状态的报告,聚合这些信息便能整体了解应用程序运行状况。 如果使用的是业务流程协调程序,则可以向业务流程协调程序的群集提供运行状况信息,以便群集可以执行相应操作。 如果使用为应用程序定制的高质量运行状况报告,则可以更轻松地检测到正在运行的应用程序存在的问题并进行修复。
在.net应用中,可以通过 Microsoft.Extensions.Diagnostics.HealthChecks 库实现运行状况检查。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号