每日前端夜话 0xB5
每日前端夜话,陪你聊前端。
每天晚上18:00准时推送。
正文共:1957 字
预计阅读时间:10 分钟
作者:Kyle Galbraith
翻译:疯狂的技术宅
来源: logrocket
在微服务架构的世界中,我们通过一系列服务构建应用。集合中的每项服务都符合以下标准:
松散耦合
可维护和可测试
可以独立部署
微服务架构中的每个服务都解决了应用中的业务问题,或至少支持一个。一个团队对应用中的一个或多个服务负责。
微服务架构可以解锁许多好处。
它们通常更容易构建和维护
服务是围绕业务问题组织的
它们可以提高生产力和速度
它们鼓励自主、独立的团队
这些好处是微服务越来越受欢迎的一个重要原因。但有一些可能会破坏这些好处的坑。如果不小心掉进去了,你将得到一个不断产生技术债的架构。
微服务之间的通信就是一个坑,假如不提前考虑就会造成严重的破坏。
该体系结构的目标是创建松散耦合的服务,并且通信在实现这一目标中起着关键作用。在本文中,我们将重点关注在微服务架构中进行通信的三种方式,每一种都有其自己的利弊和权衡。
选择服务如何相互通信时,最直接的方式往往是 HTTP。事实上,我们可以提出一个案例,即 所有 通信渠道都来自这个渠道。但是除此之外,服务之间的 HTTP 调用是服务到服务通信的可行选择。
如果我们的架构中有两个服务,它可能看起来像这样: ServiceA
可以请求并调用 ServiceB
来获取另一条信息。
1function process(name: string): Promise<boolean> { 2 /** do some ServiceA business logic 3 .... 4 .... 5 */ 6 /** 7 * call ServiceB to run some different business logic 8 */ 9 return fetch('https://service-b.com/api/endpoint') 10 .then((response) => { 11 if (!response.ok) { 12 throw new Error(response.statusText) 13 } else { 14 return response.json().then(({saved}) => { 15 return saved 16 }) 17 } 18 }) 19}
这是一段很容易理解的适合微服务架构的代码。 ServiceA
提供了一个业务逻辑。它运行其代码然后调用 ServiceB
来运行另一个业务逻辑。在这段代码中,第一个服务在返回 之前 完成等待第二个服务完成。
这里有两个服务之间进行同步的 HTTP 调用。这是一种可行的通信模式,但它确实在两种服务之间建立了耦合。
另一个选择是异步 HTTP。这可能是这样的:
1function asyncProcess(name: string): Promise<string> { 2 /** do some ServiceA business logic 3 .... 4 .... 5 */ 6 /** 7 * call ServiceB to run some different business logic 8 */ 9 return fetch('https://service-b.com/api/endpoint') 10 .then((response) => { 11 if (!response.ok) { 12 throw new Error(response.statusText) 13 } else { 14 return response.json().then(({statusUrl}) => { 15 return statusUrl 16 }) 17 } 18 }) 19}
这种变化是微妙的。现在, ServiceB
不返回 saved
属性,而是返回一个 statusUrl
。这意味着此服务现在正在接收来自第一个服务的请求,并且 立即 返回一个URL。此 URL 可用来检查请求的进度。
将两种服务之间的通信从同步转换为异步,第一个服务不再停留等待第二个服务完成,然后再返回其工作。
通过这种方法可以使服务彼此隔离,并且耦合松散。
缺点是需要在第二个服务上创建额外的 HTTP 请求,它从外部进行轮询,直到请求完成。这也引入了客户端的复杂性,因为必须检查请求的进度。
但是,异步通信允许服务直接保持松散耦合。
另一种通信模式是基于消息的通信。
与HTTP通信不同,所涉及的服务不直接相互通信。相反,服务将消息推送到其他服务订阅的消息代理。这消除了许多与 HTTP 通信相关的复杂性。
它不需要服务知道该如何相互交流,它消除了直接相互调用的服务需求。相反,所有服务都知道消息代理,并且它们将消息推送到该代理。其他服务可以订阅代理中自己关心的消息。
如果我们的应用在 Amazon Web Services 中,可以用简单通知服务(SNS)作为消息代理。现在 ServiceA
可以将消息推送到 ServiceB
监听的 SNS 主题。
1function asyncProcessMessage(name: string): Promise<string> { 2 /** do some ServiceA business logic 3 .... 4 .... 5 */ 6 /** 7 * send message to SNS that ServiceB is listening on 8 */ 9 let snsClient = new AWS.SNS() 10 let params = { 11 Message: JSON.stringify({ 12 'data': 'our message data' 13 }), 14 TopicArn: 'our-sns-topic-message-broker' 15 } 16 17 return snsClient.publish(params) 18 .then((response) => { 19 return response.MessageId 20 }) 21}
ServiceB
侦听 SNS 主题上的消息,当收到一个关心的消息时,就会执行它的业务逻辑。
这引入了它自己的复杂性。请注意, ServiceA
不再接收状态 URL 检查进度。这是因为我们只知道消息已经被发送,而不知道 ServiceB
是否已经收到了它。
这可以通过许多不同的方式解决。一种方法是将 MessageId
返回给调用者。可以用它来查询 ServiceB
,它将存储它收到的消息的 MessageId
。
注意,使用此模式的两个服务之间仍然存在一些耦合。例如, ServiceB
和 ServiceA
必须就消息结构的定义以及其中包含什么达成一致。
最后一种模式是事件驱动模式。这是另一种异步方法,它看起来完全消除了服务之间的耦合。
与消息传递模式不同,事件驱动方法不需要服务必须知道公共消息结构。服务之间的通信通过各个服务产生的事件进行。
此处仍然需要消息代理,因为各个服务会将其事件写入其中。但是与消息方法不同,消费服务不需要知道事件的细节,它们对事件的发生做出反应,而不是产生能会或可能不会传递的信息。
在形式上,这通常被称为“仅事件驱动的通信”。下面的代码和消息传递方法类似,但推送到SNS的事件是通用的。
1function asyncProcessEvent(name: string): Promise<string> { 2 /** do some ServiceA business logic 3 .... 4 .... 5 */ 6 /** 7 * call ServiceB to run some different business logic 8 */ 9 let snsClient = new AWS.SNS() 10 let params = { 11 Message: JSON.stringify({ 12 'event': 'service-a-event' 13 }), 14 TopicArn: 'our-sns-topic-message-broker' 15 } 16 17 return snsClient.publish(params) 18 .then((response) => { 19 return response.MessageId 20 }) 21}
注意,我们的 SNS 主题消息是一个简单的 event
属性。每个服务都同意以这种格式将事件推送到代理,这使得通信松散耦合。服务可以监听他们关心的事件,并且提供为响应它们而需要运行的逻辑。
此模式使服务的耦合松散,因为事件中不包含任何有效负载。此方法中的每个服务都会响应事件的发生并运行其业务逻辑。在这里,我们通过 SNS 主题发送事件。也可以使用其他事件,例如文件上传或数据库行更新。
这些是基于微服务的架构中所有可能的通信模式吗?当然不是。基于同步和异步模式进行通信的方式还有很多种。
但是这三个突出了支持同步与异步的优缺点。在选择时要考虑耦合因素,但也需要考虑开发和调试的具体情况与注意事项。
原文: https://blog.logrocket.com/methods-for-microservice-communication/
下面夹杂一些私货:也许你和高薪之间只差这一张图
2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。
愿你有个好前程,愿你月薪30K。我们是认真的 !
长按二维码,加大鹏老师微信好友
唠一唠怎样才能拿高薪
往期精选
BootstrapVue 入门
JavaScript的工作原理:引擎、运行时和调用堆栈
用 TypeScript 开发 Node.js 程序
快速上手最新的 Vue CLI 3
JavaScript 程序员可以从C ++中学到些什么
在同一基准下对前端框架进行比较
Edge 拥抱 Chromium 对前端工程师意味着什么?
使你的 JavaScript 代码简单易读
Node.js多线程完全指南
deno如何偿还Node.js的十大技术债
实战!半小时写一个脑力小游戏
CSS Flexbox 可视化手册
世界顶级公司的前端面试都问些什么
V8引擎内部机制及优化代码的5个技巧
小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。