00. 微服务架构沉思录

1. 微服务架构沉思录

关于学习微服务架构中的一些笔记和思考

1.1 微服务架构中的进程间通信

当一个单体架构应用程序升级为微服务架构之后,发生一个最为明显的变化是各个模块之间的调用不再是本地方法的调用,而是基于进程间的通信。

进程间通信的本质其实就是交换消息,微服务架构本质也是一种分布式架构。

1.1.1 进程间通信技术

进程间通信的技术一般有两种选择:基于同步请求响应的通信机制 和基于异步的消息通信机制。

1.1.1.1 基于同步请求响应的通信机制

  • 比如SOAP协议(HTTP XML),REST(HTTP JSON),gRPC(二进制序列化,Socket通信,NIO动态代理,反射)
  • 使用RPC协议的有阿里的Dubbo , Google gRPC,Facebook 的Thrift,Twitter 的 Fingle.
  • 通信框架有Netty , MINA
  • gPRC使用ProtocolBffers作为消息格式
  • REST协议有资源,动词(GET/PUT/DELTE/POST)的概念

RPC 到底是什么?

用一张图解释:
在这里插入图片描述
正如上图所示,

  • 所谓的RPC的核心无非是微服务A 将请求的方法和参数 序列化成二进制数据
  • 然后通过Netty类网络通讯框架,将二进制数据通过Scoket 发送到另外一个B微服务
  • 另外一个B微服务将收到的请求反序列化解析出来,然后将执行结果再次序列化成二进制后,通过Socket 返回。

一个RPC框架大致需要动态代理、序列化、网络请求、网络请求接受(netty实现)、动态加载、反射这些知识点

1.1.1.1.1 REST 的好处

REST好处在于:

  • 非常简单,大家都很熟悉
  • 方便测试
  • 防火墙支持友好
  • 不需要中间代理,简化系统架构
1.1.1.1.2 REST 的弊端

REST弊端在于:

  • 支持请求/响应方式通信
  • 在调用期间必须保持都在线
  • 客户端必须知道服务端的地址(URL),必须使用服务发现机制
  • 多个更新映射到HTTP动词
1.1.1.1.3 gRPC好处

gRPC好处在于:

  • 设计复杂更新操作的API非常简单
  • 具有高效,紧凑进程间通信机制,尤其在交换大量消息时
  • 支持在远程过程调用和消息传递过程中使用双向流式消息方式
  • 实现了客户端和用各种语言编写的服务端之间的互操作性
  • 可以使用Erlang 更好利用多核资源
1.1.1.1.4 gRPC弊端

gPRC弊端在于:

  • 比REST/JSON 的API机制相比需要更多的工作
  • 旧式防火墙可能不支持HTTP/2

1.1.1.2 基于异步的机遇消息通信机制

  • AMQP,比如RabbitMQ,IBM MQ,
  • STOMP

但总之不管哪种方式都需要使用服务发现。

1.2 微服务架构中的分布式事务

在单体架构中也许我们可以使用 Spring 采取注解方式@Transaction 实现本地事务。

但是微服务架构中却不再适用,分布式事务的本质是同步进程间通信

这是因为在微服务架构中,各个微服务处于不同的进程中,并没有办法像单体架构中那样操作本地事务。

而且一些消息中间件并不支持分布式事务,比如 Rabbit MQ, Apache Kafka,除非你打算放弃不使用这些。

因此在微服务架构中有些人提出使用分布式事务的解决方案:两阶段提交(JTA) 或三阶段提交(JTA)。

那么什么是两阶段提交和三阶段提交呢?

1.2.1 两阶段提交

所谓的两阶段提交原理图如下所示:
在这里插入图片描述
所谓两阶段提交的设计思路总结如下:

  • 引入一个协调者通知每个微服务参与者各自执行自己的本地事务但是不要提交,执行结果都要反馈给协调者。
  • 协调者如果收到任意一个微服务参与者事务执行失败,那么就通知其他所有微服务,进行回滚。
  • 协调者如果收到所有微服务参与者都执行成功,那么通知所有微服务可以开始提交自己执行的本地事务。

1.2.2 三阶段提交

所谓的三阶段提交则是如下图所示:
在这里插入图片描述

  • 引入一个协调者询问每个微服务参与者能否参加事务执行?
    • 协调者如果收到任意一个微服务参与者不能执行,那么就通知其他所有微服务,进行回滚。
    • 协调者如果收到所有微服务参与者都说可以执行,就通知所有微服务执行自己的本地事务但是不提交。
  • 协调者询问所有微服务的本地事务执行结果,如果都执行了,没问题,那么下发通知,全部执行事务提交。
  • 协调者接受微服务所有的事务执行结果。

上面无论是两阶段提交还是三阶段提交,其实都有一个问题:

那就是事务执行期间,所有微服务必须都有空执行本地事务,其中一个微服务不在,就无法开始。

因此这种并不是最好的解决方案。

1.2.3 更好的解决方案

另外一种解决思路是使用数据库做消息临时缓存表。

设计思路如下:

  • 协调者让每个微服务执行提交自己的本地事务
  • 然后将每个微服务的执行结果存放到数据库或消息中间件的临时缓存表中。
  • 只要一旦其中一个出错,启动补偿事务回滚,所有微服务撤销之前的事务。

1.3 微服务架构中的 API Gateway

在微服务架构中,如果没有API Gateway 会怎么样?
在这里插入图片描述
我们通过上图可以看出,这种架构存在严重的问题。

  • 客户端请求次数过多导致用户体验不佳
  • 每个客户端需要多次网络请求,那么如果出现一旦网络卡顿,很可能影响用户体验
  • 调用很多微服务,需要在本地进行数据组合
  • 手机端如果网络请求次数过多,也会导致手机电量下降过快
  • 客户端到服务端的请求次数很多,如果想提供较好的服务,必须长期保持较高的带宽。

1.3.2 API Gateway 模式

那么如果我们尝试引入 API Gateway 呢?
在这里插入图片描述
API Gateway在这里充当了反向代理的角色,屏蔽了其他微服务之间的调用。

任何客户端调用微服务都统一通过API Gateway 才能调用微服务。

由于API Gateway和其他微服务可能处于局域网内,因此就算请求很多微服务,速度也会比之前快很多。

但是这种架构设计仍然存在一些问题。

什么问题呢?

  • 移动客户端,和网页客户端可能因为平台不同,功能不同,需要不同的API 接口。
  • API Gateway 开发团队工作量过于巨大,需要整合所有微服务以及客户端的API 设计需求。

存在问题如下所示:
在这里插入图片描述

1.3.2 后端前置模式

解决上述问题的一种比较好的处理方式是使用后端前置模式。

那么什么是后端前置模式呢?
在这里插入图片描述
这种模式的设计思路是这样的:

  • 我们只提供公共层的方法调用,相当于把各个微服务整合到公共层。
  • 其他每一种客户端都由自己的客户端去维护自己的API 层。

1.3.1 API Gateway 的选择?

关于如何首先API Gateway 有多种选择,可以选择使用一些成熟的产品框架,也可以自己开发。

比如Netflix 的Zuul 经过Spring 官方团队封装后,推出的Spring Cloud Zuul。

当然,还有更好的选择是使用Spring Cloud Gateway

之所以更推荐使用SpringCloud Gateway是因为它是一个基于Spring Framework 5,Spring Boot 2 和Spring Webflux 构建的API Gateway 框架,构建在Project Reactor 之上,而Project Reactor 是一个基于NIO 的JVM 响应式框架。

1.4 关于微服务的理解

每个微服务都是自治,是可以独立部署的,不依赖其他微服务。

每个微服务部署一般部署在不同服务器上的, 从部署方面来看是分布式部署。(如果没那么多服务器也可能单个机器多个端口方式部署,也可以容器K8S 对这些微服务服务编排)

单体架构举个例子就像车原来是一体的,如果坏了,整个车都得换,现在微服务一个车拆分成了多个零件,坏了只需要换其中一个零件即可,甚至可以添加新的部件,可扩展性强。

微服务本质是各个微服务之间跨进程通信,可以通过SOAP 协议XML 方式发送,也可以通过HTTP REST JSON方式发送,也可以通过RPC 序列化类Socket 通信。

每个微服务的请求统一入口都是通过API Gateway

权限验证和拦截也应该在API Gateway 处进行验证,不知道你们有没有听过跨站拿站的故事。

试想下如果你有多个微服务,其中很多微服务密不透风,其中一个微服务一旦被攻破由于这台机器位于内网,那么将可能也会被攻破,尤其如果其他微服务也部署在这台服务器上的话。

每个微服务可以用多种语言么?理论上是可以的,但是建议统一使用一种语言,这是因为虽然每个微服务都是独立的可以用不同的语言实现,但是服务注册中心并不见得支持所有的语言,不是么?

为什么需要服务注册?

第一:微服务与微服务之间的请求是跨进程的,无论选择基于SOAP 协议的XML 传输还是基于 REST JSON 传输,或选择RPC 框架如Dubbo实现服务治理,都需要知道请求的地址。

第二:微服务的部署的IP 一般都是动态IP分配不可能那么多静态IP 给你用。

第三:弹性扩容,需要动态扩容机器部署,这些后期的一些部署IP 等信息是无法提前预知的。

因此必须有一个高可用的服务治理解决方案。

更多的思考

如果你打开官网,应该能找到这么一张图,对于java 后端开发者的我们,会有怎么样的启示呢?
在这里插入图片描述

本篇完~

发布了194 篇原创文章 · 获赞 262 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/hadues/article/details/105165708