当前位置: 首页 > 科技观察

微服务:服务如何通信?

时间:2023-03-15 20:49:07 科技观察

在微服务架构中,一个完整的应用被拆分成一组服务。这些服务需要通过接口进行协作和调用,才能形成一个完整的应用。当不同的服务部署在不同的机器上,或者同一台机器上的多个容器中时,进程间通信是不可避免的,也是非常重要的。按类型划分,进程间的通信方式有很多,比如远程过程调用的RESTfulAPI和gRPC,还有基于消息机制的异步方式。RESTfulAPI:现在比较流行前后端分离,大家对RESTfulAPI应该不陌生。REST是一种使用HTTP协议的进程间通信机制,一般使用Json传输数据;gRPC:是一个高性能、开源、通用的RPC框架,基于ProtoBuf(ProtocolBuffers)序列化协议开发,支持多种开发语言。面向服务端和移动端,基于HTTP/2设计,在单个TCP连接上带来双向流、流量控制、头部压缩、多路复用请求等特性;异步消息:使用消息中间件实现,如RabbitMQ、Kafka等。根据交互方式,会有同步和异步。同步:客户端向服务器发起请求,等待服务器响应,等待过程会造成阻塞;异步:客户端向服务端发起请求,服务端立即响应,不会造成阻塞,例如发布订阅消息队列的方式。这里有几个语言需要统一的概念:接口、客户端、服务端接口:如果使用消息机制,接口由消息通道、类型和消息格式组成;如果是基于HTTP的,则由URL组成,由HTTP动词和请求响应的格式组成;当然也可以是一个提供了一组方法的类;client、server:说起client,第一印象很容易想到浏览器和手机app。这里的客户端指的是主叫方和被叫方,服务器就是被叫方。接口的定义由服务器定义。在前后端分离之前的单体应用中,当接口方法发生变化时,代码编译会知道哪些地方需要调整,或者在IDE中搜索接口方法参考,也可以很方便处理。在微服务中,不同的服务可能由不同的团队开发,服务端接口的修改、滚动发布等都需要有很好的兼容性和可用性。一种方式是在接口上向下兼容,但是代码会随着时间的推移变得越来越复杂,例如:增加一些控制参数。接口方法新增的参数需要赋默认值。返回值也可能需要特殊处理。另一种方式是不向下兼容,所有客户端都需要调整代码来适应新的接口。在客户端代码完全调整之前,需要新旧接口共存。共存有两种方式:使用URL地址添加版本号,例如:/api/v1/xxx,/api/v2/xxx。在请求头或消息体中添加版本号,根据版本号适配接口方法,调用对应版本的逻辑返回给客户端。因此,一个设计良好的接口可以在暴露有用功能的同时隐藏实现细节。在不影响客户调用的情况下,可以扩展和修改细节。这就要求在设计界面之前需要定义界面。经过几轮审核后,将实施编码。好的设计都有自己的防腐层。由于客户端和服务器是相互独立的,有时服务器不能在一定时间内完全响应客户端的请求,这可能是由于自身故障或过载造成的。这时候客户端的请求就会被阻塞,无限等待。有几种方法可以解决这个问题:设置一个超时时间:在等待请求响应时,不要无限阻塞,设置一个超时时间,超时后返回。根据负载能力,客户端请求的数量是有限的。如果超过上限,后续请求将直接返回失败。监控客户端请求,如果失败率超过阈值,将进行熔断,使调用立即失败。现在有一些成熟的框架可以方便的进行融合处理,比如.NET中的Polly,SpringCloud中的Sentinel,Hystrix等。在传统软件中,往往使用环境变量和配置文件来配置静态地址。在部署在云端的分布式微服务程序中,地址是动态的。客户端如何找到这些地址?这需要使用服务发现。服务发现是指客户端不再依赖静态的固定地址来寻找服务器,而是根据路由名称在服务注册中心中查找服务器地址。服务器部署完成后,该地址会被写入服务注册中心。在微服务框架中,也有相关的框架来实现服务发现,例如:.NET中的consul、SpringCloud中的Eureka、Nacos等。对于实时性要求不高的场景,可以使用异步消息来实现。比如删除数据时,需要删除数据中对应的附件信息,各种操作的日志记录,流程中发送消息通知等。使用异步消息有以下优点:不需要知道接收方的地址,只需要发送消息,发送方和接收方完全解耦。可以有一个或多个消息消费者。当处理速度不够时,可以横向扩展多个消费者进行处理。消息中间件充当发送方和接收方之间的缓冲区。现在流行的开源中间件有RabbitMQ、ActiveMQ、RokcetMQ、Kafka等,在选择这些中间件时需要考虑:支持的编程语言。支持的消息标准;.是否支持持久化?延迟是否在可接受的范围内?消息能否按顺序处理?很多工作流引擎采用的是消息驱动的机制,流程需要保证消息在流转过程中是顺序处理的,否则流程数据可能会发生混乱,如何在保证消息顺序处理的同时进行横向扩展是一个难题挑战。在Kafka中可以使用分片来解决。以上介绍了一些服务间常用的通信方式。了解了基本逻辑后,在实践中,微服务使用.NET技术栈或者Java技术栈就不难了。