微服务的三种通讯方法

做者:Kyle Galbraith

翻译:疯狂的技术宅javascript

原文:https://blog.logrocket.com/me...前端

未经容许严禁转载java

在微服务架构的世界中,咱们经过一系列服务构建应用。集合中的每项服务都符合如下标准:程序员

  • 松散耦合
  • 可维护和可测试
  • 能够独立部署

微服务架构中的每一个服务都解决了应用中的业务问题,或至少支持一个。一个团队对应用中的一个或多个服务负责。面试

微服务架构能够解锁许多好处。数据库

  • 它们一般更容易构建和维护
  • 服务是围绕业务问题组织的
  • 它们能够提升生产力和速度
  • 它们鼓励自主、独立的团队

这些好处是微服务愈来愈受欢迎的一个重要缘由。但有一些可能会破坏这些好处的坑。若是不当心掉进去了,你将获得一个不断产生技术债的架构。json

微服务之间的通讯就是一个坑,假如不提早考虑就会形成严重的破坏。segmentfault

该体系结构的目标是建立松散耦合的服务,而且通讯在实现这一目标中起着关键做用。在本文中,咱们将重点关注在微服务架构中进行通讯的三种方式,每一种都有其本身的利弊和权衡。api

HTTP通讯

选择服务如何相互通讯时,最直接的方式每每是 HTTP。事实上,咱们能够提出一个案例,即全部通讯渠道都来自这个渠道。可是除此以外,服务之间的 HTTP 调用是服务到服务通讯的可行选择。服务器

若是咱们的架构中有两个服务,它可能看起来像这样: ServiceA 能够请求并调用 ServiceB 来获取另外一条信息。

function process(name: string): Promise<boolean> {
    /** do some ServiceA business logic
        ....
        ....
    */
    /**
     * call ServiceB to run some different business logic
    */
    return fetch('https://service-b.com/api/endpoint')
        .then((response) => {
            if (!response.ok) {
                throw new Error(response.statusText)
            } else {
                return response.json().then(({saved}) => {
                    return saved
                })
            }
        })
}

这是一段很容易理解的适合微服务架构的代码。 ServiceA 提供了一个业务逻辑。它运行其代码而后调用 ServiceB 来运行另外一个业务逻辑。在这段代码中,第一个服务在返回以前完成等待第二个服务完成。

这里有两个服务之间进行同步的 HTTP 调用。这是一种可行的通讯模式,但它确实在两种服务之间创建了耦合。

另外一个选择是异步 HTTP。这多是这样的:

function asyncProcess(name: string): Promise<string> {
    /** do some ServiceA business logic
        ....
        ....
    */
    /**
     * call ServiceB to run some different business logic
    */
    return fetch('https://service-b.com/api/endpoint')
        .then((response) => {
            if (!response.ok) {
                throw new Error(response.statusText)
            } else {
                return response.json().then(({statusUrl}) => {
                    return statusUrl
                })
            }
        })
}

这种变化是微妙的。如今, ServiceB 不返回 saved 属性,而是返回一个 statusUrl。这意味着此服务如今正在接收来自第一个服务的请求,而且当即返回一个URL。此 URL 可用来检查请求的进度。

将两种服务之间的通讯从同步转换为异步,第一个服务再也不停留等待第二个服务完成,而后再返回其工做。

经过这种方法可使服务彼此隔离,而且耦合松散。

缺点是须要在第二个服务上建立额外的 HTTP 请求,它从外部进行轮询,直到请求完成。这也引入了客户端的复杂性,由于必须检查请求的进度。

可是,异步通讯容许服务直接保持松散耦合。

消息通讯

另外一种通讯模式是基于消息的通讯。

与HTTP通讯不一样,所涉及的服务不直接相互通讯。相反,服务将消息推送到其余服务订阅的消息代理。这消除了许多与 HTTP 通讯相关的复杂性。

它不须要服务知道该如何相互交流,它消除了直接相互调用的服务需求。相反,全部服务都知道消息代理,而且它们将消息推送到该代理。其余服务能够订阅代理中本身关心的消息。

若是咱们的应用在 Amazon Web Services 中,能够用简单通知服务(SNS)做为消息代理。如今 ServiceA 能够将消息推送到 ServiceB 监听的 SNS 主题。

function asyncProcessMessage(name: string): Promise<string> {
    /** do some ServiceA business logic
        ....
        ....
    */
    /**
     * send message to SNS that ServiceB is listening on
    */
    let snsClient = new AWS.SNS()
    let params = {
        Message: JSON.stringify({
            'data': 'our message data'
        }),
        TopicArn: 'our-sns-topic-message-broker'
    }

    return snsClient.publish(params)
        .then((response) => {
            return response.MessageId
        })
}

ServiceB 侦听 SNS 主题上的消息,当收到一个关心的消息时,就会执行它的业务逻辑。

这引入了它本身的复杂性。请注意,ServiceA 再也不接收状态 URL 检查进度。这是由于咱们只知道消息已经被发​​送,而不知道 ServiceB 是否已经收到了它。

这能够经过许多不一样的方式解决。一种方法是将 MessageId 返回给调用者。能够用它来查询 ServiceB,它将存储它收到的消息的 MessageId

注意,使用此模式的两个服务之间仍然存在一些耦合。例如,ServiceBServiceA 必须就消息结构的定义以及其中包含什么达成一致。

事件驱动的通讯

最后一种模式是事件驱动模式。这是另外一种异步方法,它看起来彻底消除了服务之间的耦合。

与消息传递模式不一样,事件驱动方法不须要服务必须知道公共消息结构。服务之间的通讯经过各个服务产生的事件进行。

此处仍然须要消息代理,由于各个服务会将其事件写入其中。可是与消息方法不一样,消费服务不须要知道事件的细节,它们对事件的发生作出反应,而不是产生能会或可能不会传递的信息。

在形式上,这一般被称为“仅事件驱动的通讯”。下面的代码和消息传递方法相似,但推送到SNS的事件是通用的。

function asyncProcessEvent(name: string): Promise<string> {
    /** do some ServiceA business logic
        ....
        ....
    */
    /**
     * call ServiceB to run some different business logic
    */
    let snsClient = new AWS.SNS()
    let params = {
        Message: JSON.stringify({
            'event': 'service-a-event'
        }),
        TopicArn: 'our-sns-topic-message-broker'
    }

    return snsClient.publish(params)
        .then((response) => {
            return response.MessageId
        })
}

注意,咱们的 SNS 主题消息是一个简单的 event 属性。每一个服务都赞成以这种格式将事件推送到代理,这使得通讯松散耦合。服务能够监听他们关心的事件,而且提供为响应它们而须要运行的逻辑。

此模式使服务的耦合松散,由于事件中不包含任何有效负载。此方法中的每一个服务都会响应事件的发生并运行其业务逻辑。在这里,咱们经过 SNS 主题发送事件。也可使用其余事件,例如文件上传或数据库行更新。

结论

这些是基于微服务的架构中全部可能的通讯模式吗?固然不是。基于同步和异步模式进行通讯的方式还有不少种。

可是这三个突出了支持同步与异步的优缺点。在选择时要考虑耦合因素,但也须要考虑开发和调试的具体状况与注意事项。


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎继续阅读本专栏其它高赞文章:


相关文章
相关标签/搜索