我创建了一个 REST API - 简而言之,我的客户点击了一个特定的 URL,她得到了一个 JSON 响应。
在内部,当 URL 被点击时,一个相当复杂的过程开始了,并且在使用微服务架构时涉及到各种服务。
我观察到一些性能瓶颈并决定切换到消息队列系统。这个想法是,现在,一旦用户点击 URL,就会在内部消息队列上发布一个请求,等待它被使用。该消费者将处理并发布回队列,这将发生很多次,直到最终,为用户提供服务的同一节点将收到处理后的响应以传递给用户。
现在正在使用异步“即发即弃”模式。但我的问题是,一旦处理的结果返回并且没有阻塞(即它可以处理多个请求直到收到响应),为特定人提供服务的节点如何记住它正在为谁服务?如果有什么不同的话,我的堆栈看起来有点像这样:TomCat、Spring、Kubernetes 和 RabbitMQ。
总而言之,请求节点(其工作是向队列中推送项目)如何与请求 JSON 响应(即客户端正在等待 JSON 响应)的客户端保持开放连接并接收返回的数据正确的客户?
最佳答案
根据您对客户端的控制程度,您有几个不同的场景。
如果无法更改客户端行为,您将不得不保持 session 打开,直到请求未被完全处理。这可以通过使用一个工作池( future /协程、线程或进程)来实现,其中每个工作人员为给定的请求保持 session 打开。
这种方法几乎没有缺点,我会保留它作为最后的手段。首先,您将只能处理与您的池大小成比例的有限数量的并发请求。最后,由于您的处理在队列后面,您的前端将无法估计完成任务需要多长时间。这意味着您将不得不处理容易失败的长时间 session (如果用户放弃了怎么办?)。
如果可以更改客户端行为,最常见的方法是使用完全异步的流程。当客户端发起一个请求时,它被放置在队列中并返回一个任务标识符。客户端可以使用给定的 TaskId 来轮询状态更新。每次客户请求更新任务时,您只需检查它是否已完成并做出相应的响应。当任务仍在进行中时,一种常见的模式是让前端在重试之前将估计的时间返回给客户端。这允许您的服务器控制客户端轮询的频率。如果您的架构支持它,您可以加倍努力并提供有关进度的信息。
任务进行中的响应示例:
{"status": "in_progress",
"retry_after_seconds": 30,
"progress": "30%"}
更复杂但更优雅的解决方案是使用 HTTP 回调。简而言之,当客户端请求新任务时,它会提供一个元组(URL,方法),服务器可以使用它来表示处理完成。然后它等待服务器将信号发送到给定的 URL。可以看到更好的解释here .在大多数情况下,这种解决方案是多余的。但我认为值得一提。
关于spring - 带有内部消息队列的前端 REST API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53525239/
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi
如果我在模型中设置验证消息validates:name,:presence=>{:message=>'Thenamecantbeblank.'}我如何让该消息显示在闪光警报中,这是我迄今为止尝试过的方法defcreate@message=Message.new(params[:message])if@message.valid?ContactMailer.send_mail(@message).deliverredirect_to(root_path,:notice=>"Thanksforyourmessage,Iwillbeintouchsoon")elseflash[:error]
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)
假设我有一个类A,里面有一些方法。假设stringmethodName是这些方法之一,我已经知道我想给它什么参数。它们在散列中{'param1'=>value1,'param2'=>value2}所以我有:params={'param1'=>value1,'param2'=>value2}a=A.new()a.send(methodName,value1,value2)#callmethodnamewithbothparams我希望能够通过传递我的哈希以某种方式调用该方法。这可能吗? 最佳答案 确保methodName是一个符号,而