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

微服务的三种通信方式

时间:2023-03-17 11:58:03 科技观察

在微服务架构的世界里,我们通过一系列的服务来构建应用。集合中的每个服务都满足以下标准:松散耦合可维护和可测试可独立部署微服务架构中的每个服务解决应用程序中的一个业务问题,或至少支持一个业务问题。一个团队负责应用程序中的一项或多项服务。微服务架构可以带来许多好处。它们通常更容易构建和维护服务围绕业务问题进行组织它们可以提高生产力和速度它们鼓励自主、独立的团队这些好处是微服务越来越受欢迎的一个重要原因。但是有些陷阱会破坏这些好处。如果你不小心陷入其中,你最终会得到一个不断产生技术债务的架构。微服务之间的通信是一个坑,如果不提前考虑,会造成严重的损害。该架构的目标是创建松散耦合的服务,而通信在实现这一目标中起着关键作用。在本文中,我们将重点介绍在微服务架构中进行通信的三种方式,每种方式都有其优缺点和权衡。HTTP通信选择服务之间的通信方式时,最直接的方式通常是HTTP。事实上,我们可以假设所有的沟通渠道都来自这个渠道。但除此之外,服务之间的HTTP调用是服务到服务通信的可行选择。如果我们的架构中有两个服务,它可能看起来像这样:ServiceA可以请求和调用ServiceB以获取另一条信息。functionprocess(name:string):Promise{/**dosomeServiceAbusinesslogic......*//***callServiceBtorunsomedifferentbusinesslogic*/returnfetch('https://service-b.com/api/endpoint').then((response)=>{if(!response.ok){thrownewError(response.statusText)}else{returnresponse.json().then(({saved})=>{returnsaved})}})}这个是一段易于理解的代码,适用于微服务架构。ServiceA提供业务逻辑。它运行其代码,然后调用ServiceB来运行另一个业务逻辑。在此代码中,第一个服务完成,等待第二个服务完成后再返回。这是两个服务之间的同步HTTP调用。这是一种可行的通信模式,但它确实在两个服务之间创建了耦合。另一种选择是异步HTTP。这可能看起来像这样:com/api/endpoint').then((response)=>{if(!response.ok){thrownewError(response.statusText)}else{returnresponse.json().then(({statusUrl})=>{returnstatusUrl})}})}这种变化是微妙的。现在,ServiceB不再返回已保存的属性,而是返回一个statusUrl。这意味着此服务现在正在接收来自第一个服务的请求并立即返回一个URL。此URL可用于检查请求的进度。将两个服务之间的通信从同步切换到异步,第一个服务不再等待第二个服务完成后再返回其工作。这种方法使服务彼此隔离并松散耦合。缺点是需要在第二个服务上创建一个额外的HTTP请求,该请求在外部轮询直到请求完成。这也给客户端带来了复杂性,因为必须检查请求的进度。然而,异步通信允许服务直接保持松散耦合。消息通信另一种通信模式是基于消息的通信。与HTTP通信不同,涉及的服务不直接相互通信。相反,服务将消息推送到其他服务订阅的消息代理。这消除了许多与HTTP通信相关的复杂性。它不需要服务知道如何相互交谈,也不需要服务直接相互调用。相反,所有服务都知道消息代理,并将消息推送给它。其他服务可以在代理中订阅他们关心的消息。如果我们的应用程序在AmazonWebServices中,我们可以使用简单通知服务(SNS)作为消息代理。现在ServiceA可以向ServiceB监听的SNS主题推送消息。functionasyncProcessMessage(name:string):Promise{/**dosomeServiceAbusinesslogic.......*//***sendmessagetoSNSthatServiceBislisteningon*/letsnsClient=newAWS.SNS()letparams={Message:JSON.stringify({'data':'ourmessagedata'}),TopicArn:'our-sns-topic-message-broker'}returnsnsClient.publish(params).then((response)=>{returnresponse.MessageId})}ServiceB监听SNStopic当收到关注的消息时,会执行其业务逻辑。这引入了它自己的复杂性。请注意,ServiceA不再接收用于检查进度的状态URL。这是因为我们只知道消息发送了,不知道ServiceB有没有收到。这可以通过许多不同的方式解决。一种方法是将MessageId返回给调用者。这可用于查询ServiceB,后者将存储它收到的消息的MessageId。请注意,使用此模式的两个服务之间仍然存在一些耦合。例如,ServiceB和ServiceA必须就消息结构的定义以及其中包含的内容达成一致。事件驱动通信最后一种模式是事件驱动模式。这是另一种异步方法,似乎可以完全消除服务之间的耦合。与消息传递模式不同,事件驱动方法不要求服务知道通用消息结构。服务之间的通信通过每个服务生成的事件发生。这里仍然需要消息代理,因为各个服务会将它们的事件写入其中。但与消息方法不同,消费服务不需要知道事件的细节,它们对事件的发生做出反应,而不是产生可能会或可能不会传递的信息。形式上,这通常被称为“仅事件驱动的通信”。下面的代码类似于消息传递方法,但是推送到SNS的事件是通用的。functionasyncProcessEvent(name:string):Promise{/**dosomeServiceAbusinesslogic.......*//***callServiceBtorunsomedifferentbusinesslogic*/letsnsClient=newAWS.SNS()letparams={Message:JSON.stringify({'event':'service-a-event'}),TopicArn:'our-sns-topic-message-broker'}returnsnsClient.publish(params).then((response)=>{returnresponse.MessageId})}注意,我们的SNS主题消息是一个简单的事件属性。每个服务都同意以这种格式将事件推送到代理,这使得通信松散耦合。服务可以监听他们关心的事件并提供他们需要运行的逻辑来响应这些事件。这种模式使服务的耦合松散,因为事件中不包含有效负载。此方法中的每个服务都会响应事件的发生并运行其业务逻辑。在这里,我们通过SNS主题发送事件。也可以使用其他事件,例如文件上传或数据库行更新。结论这些都是基于微服务的架构中可能的通信模式吗?当然不是。还有许多其他基于同步和异步模式的通信方式。但这三个突出了支持同步与异步的优缺点。选择时要考虑耦合因素,但也要考虑开发调试的具体情况和注意事项。