背景:
我正在构建一个应用程序,建议的架构是基于微服务架构的事件/消息驱动。
做事的单一方式是我有一个用户/HTTP 请求,并且执行一些具有直接同步响应 的命令。因此,响应相同的用户/HTTP 请求是“无忧无虑的”。
问题:
用户发送一个 HTTP 请求 到 UI 服务(有多个 UI 服务),它会触发一些事件到队列(Kafka/RabbitMQ/any)。一个 N 服务拾取该事件/消息在此过程中发挥了一些作用,然后在某个时候,同一个 UI 服务应该拾取响应并将其返回给发起 HTTP 请求的用户。请求处理是 ASYNC 但 User/HTTP REQUEST->RESPONSE 根据您的典型 HTTP 交互是 SYNC。
问题: 在这个不可知论/事件驱动的世界中,如何向发起操作(通过 HTTP 与用户交互的服务)的同一 UI 服务发送响应?
我目前的研究 我一直在环顾四周,似乎有些人正在使用 WebSockets 解决这个问题。
但复杂的层面是需要有一些映射 (RequestId->Websocket(Client-Server)) 的表,用于“发现”网关中的哪个 Node 具有用于某些特定响应的 websocket 连接。但是,即使我理解了问题和复杂性,我仍然无法找到任何可以为我提供有关如何在实现层解决此问题的信息的文章。 并且这仍然不是一个可行的选择,因为第三方集成,例如期望 REQUEST->RESPONSE 的支付提供商 (WorldPay) - 特别是在 3DS 验证方面。
所以我有点不愿意认为 WebSockets 是一种选择。但是,即使 WebSockets 对于面向 Web 的应用程序来说没问题,但对于连接到外部系统的 API 来说,这并不是一个很好的架构。
** ** ** 更新: ** ** **
即使对于具有 202 Accepted Location header 和 retry-after header 的 WebService API 来说,长轮询是一种可能的解决方案对于高并发和高能力的网站来说不会是高性能的。
想象一下,有大量的人试图在他们提出的每个请求上获取事务状态更新,而您必须使 CDN 缓存无效(现在就去解决这个问题!哈)。
但最重要且与我的案例相关的第 3 方 API,例如支付系统,其中 3DS 系统具有由支付提供商系统处理的自动重定向,并且他们期望典型的 REQUEST/RESPONSE 流程,因此这个模型对我不起作用,套接字模型也不起作用。
由于这个用例,HTTP REQUEST/RESPONSE 应该以典型的方式处理,我有一个愚蠢的客户端,期望在后端处理处理的复杂性。
所以我正在寻找一种解决方案,在外部我有一个典型的
长轮询的示例,但此模型不适用于 3rd 方 API,例如 Request->Response(SYNC) 并且状态的复杂性(系统的 ASYNCrony)在内部处理3DS 重定向 上的支付提供商,这不在我的控制范围内。 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
最佳答案
正如我所预料的那样——人们试图将所有东西都融入一个概念,即使它不适合那里。这不是批评,这是根据我的经验以及阅读您的问题和其他答案后的观察。
是的,您说得对,微服务架构基于异步消息传递模式。但是,当我们谈论 UI 时,我想到的可能有两种情况:
UI 需要立即响应(例如读取操作或用户期望立即响应的那些命令)。 这些不必是异步的。如果屏幕上需要立即响应,为什么要增加消息传递和异步的开销?没有意义。微服务架构应该解决问题,而不是通过增加开销来创建新问题。
UI 可以重构以容忍延迟响应(例如,UI 可以提交命令、接收确认,并让用户在准备响应时做其他事情,而不是等待结果)。在这种情况下,您可以引入异步。 gateway 服务(UI 直接与之交互)可以编排异步处理(等待完成事件等),并且在准备好后,它可以与 UI 进行通信。我见过在这种情况下使用 SignalR 的 UI,网关服务是一个接受套接字连接的 API。如果浏览器不支持套接字,理想情况下它应该回退到轮询。无论如何,重要的一点是,这只能在意外情况下起作用:UI 可以容忍延迟回答。
如果微服务确实与您的情况相关(案例 2),则相应地构建 UI 流,并且后端的微服务不应该存在挑战。在这种情况下,您的问题归结为将事件驱动架构应用于一组服务(边缘是连接事件驱动和 UI 交互的网关微服务)。这个问题(事件驱动服务)是可以解决的,你知道的。您只需要决定是否可以重新考虑您的 UI 是如何工作的。
关于node.js - 如何在微服务/事件驱动架构中处理 HTTP 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50986816/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f