如何在微服务/事件驱动架构中处理HTTP请求?

Jon*_*rft 27 rest websocket node.js apache-kafka microservices

背景:

我正在构建一个应用程序,所提出的架构是微服务架构上的事件/消息驱动.

做事的单一方式是我有一个User/HTTP request和那个动作一些直接的命令synchronous response.因此,响应相同的用户/ HTTP请求是"无忧无虑".

在此输入图像描述

问题:

用户发送HTTP requestUI服务(有多个UI服务),该触发某些事件到队列(卡夫卡/ RabbitMQ的/有).N个服务选择事件/消息在此过程中做了一些魔术,然后在某些时候,相同的UI服务应该选择响应并将其返回给发起HTTP请求的用户.请求处理ASYNC,但User/HTTP REQUEST->RESPONSESYNC按照典型的HTTP交互.

问题: 如何在此不可知/事件驱动的世界中向发起操作的同一UI服务(通过HTTP与用户交互的服务)发送响应?

到目前为止,我的研究 一直在环顾四周,似乎有些人正在使用WebSockets解决这个问题.

但是复杂性层需要有一些映射表,(RequestId->Websocket(Client-Server))用于"发现"网关中的哪个节点具有用于某些特定响应的websocket连接.但即使我理解了问题和复杂性,我也陷入困境,我找不到任何可以提供有关如何在实现层解决此问题的信息的文章.这还不是因为第三方集成如预期支付服务提供商(WorldPay的)的一个可行的选择REQUEST->RESPONSE-特别是关于3DS验证.

所以我不知道如何认为WebSockets是一个选项.但即使WebSockets适用于Webfacing应用程序,连接到外部系统的API也不是一个很好的架构.

******更新:******

即使长轮询是带有202 Accepteda Location header和a 的WebService API的可能解决方案,retry-after header它也不具备高并发性和高性能网站的性能.想象一下,有很多人试图在他们提出的每个请求上更新事务状态,你必须使CDN缓存无效(现在去玩这个问题!哈).

但最重要且与我的情况相关的是我的第三方API,例如支付系统,其中3DS系统具有由支付提供商系统处理的自动重定向,并且他们期望是典型的REQUEST/RESPONSE flow,因此这种模型对我和套接字都不起作用模型会起作用.

由于这个用例,HTTP REQUEST/RESPONSE应该以典型的方式处理,我有一个愚蠢的客户端,期望在后端处理进动的复杂性.

所以我正在寻找一个解决方案,在外部我有一个典型的Request->Response(SYNC)和状态的复杂性(系统的ASYNCrony)在内部处理

长轮询的一个示例,但此模型不适用于第三方API,例如支付提供商,3DS Redirects这不在我的控制之内.

 POST /user
    Payload {userdata}
    RETURNs: 
        HTTP/1.1 202 Accepted
        Content-Type: application/json; charset=utf-8
        Date: Mon, 27 Nov 2018 17:25:55 GMT
        Location: https://mydomain/user/transaction/status/:transaction_id
        Retry-After: 10

GET 
   https://mydomain/user/transaction/status/:transaction_id
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Ten*_*giz 14

正如我所期望的 - 人们试图将所有东西都融入一个概念中,即使它不适合那里。这不是批评,这是根据我的经验以及阅读您的问题和其他答案后的观察。

是的,您是对的,微服务架构基于异步消息传递模式。但是,当我们谈论 UI 时,我认为有两种可能的情况:

  1. UI 需要立即响应(例如,读取操作或用户希望立即得到答复的那些命令)。这些不必是异步的。如果屏幕上需要立即响应,为什么要增加消息传递和异步的开销?没有意义。微服务架构应该通过增加开销来解决问题而不是创建新问题。

  2. UI 可以重构以容忍延迟响应(例如,无需等待结果,UI 可以只提交命令、接收确认,并在准备响应时让用户做其他事情)。在这种情况下,您可以引入异步。该网关服务(与直接用户界面进行互动)可以协调异步处理(等待完整的事件等),并在准备好时,它可以回到传达到用户界面。我见过在这种情况下使用 SignalR 的 UI,网关服务是一个接受套接字连接的 API。如果浏览器不支持套接字,理想情况下它应该回退到轮询。无论如何,重要的一点是,这只能在偶然情况下起作用:UI 可以容忍延迟答案

如果微服务确实与您的情况相关(案例 2),则相应地构建 UI 流程,并且后端的微服务不应该有挑战。在这种情况下,您的问题归结为将事件驱动架构应用于服务集(边缘是连接事件驱动和 UI 交互的网关微服务)。这个问题(事件驱动服务)是可以解决的,你知道。您只需要决定是否可以重新思考 UI 的工作方式。


jak*_*cks 1

不幸的是,我相信您可能必须使用长轮询或网络套接字来完成类似的事情。您需要将某些内容“推送”给用户,或者保持 http 请求打开,直到有内容返回。

为了处理将数据返回给实际用户,您可以使用类似于socket.io的东西。当用户连接时,socket.io 会创建一个 id。每当用户连接时,您都会将用户 ID 映射到 socket.io 为您提供的 ID。一旦每个请求附加了一个用户 ID,您就可以将结果发送回正确的客户端。流程大概是这样的:

网络请求订单(带有数据和用户 ID 的 POST)

ui 服务将订单放入队列(此订单应具有 userId)

x 个按顺序运行的服务(每次都传递 userId)

ui 服务从主题消费。在某些时候,数据会出现在该主题上。它消耗的数据具有 userId,ui 服务查找映射以找出要发送到哪个套接字。

用户界面上运行的任何代码都需要是事件驱动的,因此它将在没有原始请求上下文的情况下处理数据推送。你可以使用像redux这样的东西。本质上,您可以让服务器在客户端上创建 redux 操作,它工作得很好!

希望这可以帮助。