当前位置: 首页 > 知识库问答 >
问题:

HTTP服务器推送:服务到服务,不带浏览器

苗森
2023-03-14

我正在开发一个基于云的后端HTTP服务,该服务将公开用于与一些on-prem系统的集成。客户机系统是由外部供应商定制的,它们是带有自己数据库的后端系统。这些系统部署在我们客户的公司中,我们无法访问它们,也无法控制它们。我们向供应商提供我们的API规范,他们实现客户机代码。

我的服务与客户交换的数据格式基于XML,并遵循一定的标准。供应商用不同的编程语言实现他们的客户机系统,随着时间的推移,新的供应商将出现。我希望尽可能多的客户能够使用我的服务。

我的大多数服务API都类似于REST:它接收HTTP请求,处理它们,然后发回HTTP响应。

此外,我的服务积累了一些数据状态变化,需要定期将这些数据推送到客户端系统。由于以下限制,这个用例似乎不适合传统的客户机-服务器HTTP请求-响应模型。

>

同时,我的服务涉众需要记录确认数据状态通知已被客户端系统接受,因此像Amazon SNS这样的fire and forget系统似乎不适用。

我考虑了一些解决这个问题的方法,但我不确定我是否遗漏了一些简单的选项或一些已经解决了这个问题的技术。因此这个问题。

问题文本更新:选项移到我自己的答案。

  • REST API,具有从服务器到客户端的主动推送通知

共有2个答案

呼延钱明
2023-03-14

解决服务器→客户端通知与来自客户端的ack问题的WebSockets的一种替代方案似乎是gRPC。

  • 它支持双向流模式下服务器和客户端之间的双向通信
  • 它在HTTP 2.0之上工作。在我们的例子中,通过HTTP端口运行至关重要
  • 有多种流行语言和平台的客户端和服务器生成器。一件好事是,我可以与供应商共享协议定义文件,并且可以确保我的服务和他们的客户使用相同的语言

缺点:

  • 与HTTP相比,支持的语言和平台并不多。如果基于HTTP 1.1,问题中的替代方案C将更易于访问。WebSockets的存在时间也更长,我预计会比gRPC更广泛地采用。
  • 根据常见问题解答,并非所有gRPC实现目前都支持数据的XML格式。为了传输XML,我的服务及其客户端必须将XML消息作为gRPC协议消息中的字节数组传输。
  • 使用gRPC,TLS终止无法在通用HTTP 1.1负载均衡器上完成。需要Traefik等应用层HTTP/2感知反向代理(负载均衡器)。
    有这样和这样的方法来允许HTTP 1.1兼容协议,但它们有自己的限制,例如可用客户端数量有限或必要的客户端自定义。
东方琪
2023-03-14

在我的团队的帮助下,我最终自己找到了我的问题的答案。对于像我这样带着“如何安排从我的服务向其客户发送通知”的问题来到这里的人,这里有可用选项的概述。

这是客户端打开endpointiself的时候。只要服务有一些通知要传递,该服务就会调用客户端的endpoint。这样,客户机还充当服务,因此在通知传递期间,客户机和服务交换角色。

使用WebHooks,客户端必须能够使用已知地址打开endpoint。如果客户机的软件在NAT或防火墙后工作,或者客户机是浏览器或移动应用程序,这就很复杂了。

服务需要准备好,客户端的WebHookendpoint可能并不总是在线的,也可能并不总是健康的。

另一个问题是流量控制:应在服务中采取特殊措施,以免大量连接、请求和/或数据淹没客户端。

在这种情况下,客户端仍然是客户端,服务仍然是服务,这与WebHooks不同。该服务提供了一个endpoint,客户端可以在其中不断请求新的通知。此选项的优点是它不会更改连接方向和请求-响应方向,因此它可以很好地与基于HTTP的服务配合使用。

需要注意的是,如果通知丢失是不可接受的,轮询API应该具有一些丰富的语义,以便合理可靠。谷歌Pub/Sub pull和亚马逊SQS就是很好的例子。

以下是几点考虑:

>

  • 接收和删除通知应该是单独的操作。否则,如果服务在将通知发送给客户端之前删除了通知,而客户端未能处理该通知,则该通知将永远丢失。当删除操作与接收分离时,客户端被迫显式执行删除操作,这通常发生在成功处理之后。

    如果客户端收到通知但尚未删除它,则让其他参与者(可能是同一客户端的并发进程)处理相同的通知可能是不可取的。因此,在首次收到通知后,必须隐藏通知以防止接收。

    如果由于错误、网络丢失或进程崩溃,客户端未能在合理时间内删除通知,服务必须使通知可见,以便再次接收。这是一种重试机制,允许最终处理通知。

    如果服务没有要传递的通知,它应该通过不立即传递空响应来阻止客户端的呼叫一段时间。否则,如果客户机在循环中轮询并立即响应,循环迭代将很短,客户机将向服务发出过多请求,从而增加网络、解析负载和请求计数。一个很好的特性是,一旦出现要传递的通知,服务就会解除阻止并响应客户端。这有时被称为“长轮询”。

    通过HTTP服务器发送事件,客户端打开HTTP连接并向服务发送请求,然后服务可以发送多个事件(通知),而不是单个响应。连接是长期存在的,服务可以在事件准备就绪后立即发送事件。

    缺点是通信是单向的,如果客户端成功处理了事件,则无法通知服务。因为没有这种反馈,服务可能很难控制事件的速率以防止压倒客户端。

    WebSocket是为了实现任意双向通信而创建的,因此这是服务向客户端发送通知的可行选项。客户端还可以将处理确认发送回服务。

    WebSocket已经存在了一段时间,应该得到许多框架和语言的支持。WebSocket连接始于HTTP 1.1连接,因此HTTPS上的WebSocket应该得到许多负载平衡器和反向代理的支持。

    WebSocket通常与浏览器和移动客户端一起使用,很少用于服务对服务的通信

    gRPC在某种程度上类似于WebSocket,它支持任意双向通信。gRPC的优点是它以协议和消息格式定义文件为中心。这些文件用于生成对客户端和服务开发人员至关重要的代码。

    gRPC用于服务到服务通信,并且支持带有grpc-web的浏览器客户端。

    gRPC支持多种流行编程语言和平台,但支持范围比HTTP要窄。

    gRPC在HTTP/2之上工作,这可能会给反向代理和负载平衡器带来困难,比如TLS终止。

    最后,服务和客户端可以使用消息队列作为通知的传递机制。服务将通知放在队列上,客户端从队列中接收它们。队列可以由RabbitMQ、Kafka、Celery、Google PubSub、Amazon SQS等许多系统之一提供。具有不同属性的队列系统有多种选择,选择一个本身就是一个挑战。例如,也可以使用数据库来模拟队列。

    必须在服务和拥有队列的客户之间决定,即谁为队列付费。无论哪种方式,只要服务需要向其推送通知,队列系统和队列都应该可用,否则通知将丢失(除非服务在内部使用另一个队列缓冲它们)。

    队列通常用于服务到服务的通信,但某些技术也允许浏览器作为客户端。

    值得注意的是,在上面列出的其他选项中,服务端可能会使用“隐式”内部队列。其中一个原因是防止在没有可用的客户端接收通知时丢失通知。还有很多其他好的理由,比如让客户端以自己的速度处理通知,允许最大化处理吞吐量,允许以固定容量处理尖峰流量。

    在该选项中,队列“显式”用作传递机制,即服务不在队列前面放置任何其他机制(HTTP、gRPC或WebSocketendpoint),并允许客户端直接从队列接收通知。

    消息传递在组织微服务通信中很流行。

    在所有选项中,必须决定服务、客户端和业务是否可以容忍通知丢失。如果可以由于处理错误、不可用等原因丢失通知,则可以选择一些更简单的技术选择。

    从服务端监控客户端处理错误是很有价值的。通过这种方式,服务所有者无需询问客户就可以知道哪些客户更容易崩溃。

    如果使用了队列(隐式或显式),那么监控队列长度和最早通知的时间是很有价值的。它让服务所有者判断客户机中的数据可能有多陈旧。

    如果通知的传递是以只有在客户端成功处理后才删除通知的方式组织的,那么当客户端无法处理时,相同的通知可能会卡在无限接收循环中。这种通知有时被称为“毒药消息”。服务或排队系统应删除毒药消息,以防止客户端卡在无限循环中。一种常见的做法是将毒药消息移动到一个特殊的地方,有时称为“死信队列”,以便以后进行人工干预。

  •  类似资料:
    • 服务器端提供了比较多的关于推送的 API,包括广播,多播和单播方式的推送,还有超时,心跳,推送事件等设置。 Timeout 字段 该字段用于设置推送空闲超时。默认值为 120 秒,即 2 分钟。 当服务器发布了推送主题后(后面会专门介绍推送),客户端会跟服务器端保持一个长连接,如果达到超时时间,仍然没有任何消息推送给客户端,则返回 nil,此时,如果客户端仍然在线的话,则会立即再次发送获取推送主题

    • Hprose 2.0 最大的亮点就是增加了推送功能的支持,而且这个功能的增加是在不修改现有通讯协议的方式下实现的,因此,这里的推送服务,即使不是 Hprose 2.0 的客户端或者服务器也可以使用。 当然,在旧版本的客户端调用推送服务,或者在旧版本的服务器上自己实现推送,需要多写一些代码。所以,如果你所使用的语言支持 Hprose 2.0,那幺推荐直接使用 Hprose 2.0 的推送 API 来

    • 问题内容: 在此处阅读有关服务器推送的信息。 我想将数据从Web应用程序实时推送到客户端。 我一直在将TCP套接字作为选项之一。 对于HTTP,我在这里找到了各种Java,PHP,Python和其他框架。但是我不知道这些工具是否支持Push。 您对实施服务器推送有什么建议和框架? 您会倡导使用哪种语言,为什么? 问题答案: 我现在正在使用Orbited,太好了! 如果您正在聊天或订阅类型的东西,请

    • ?> 完全协程化的Http服务器实现,Co\Http\Server继承自Co\Server,在此不再赘述,只说差异。 与 Http\Server 的不同之处: 可以在运行时动态地创建、销毁 对连接的处理是在单独的子协程中完成,客户端连接的Connect、Request、Response、Close是完全串行的 !> 需要v4.4.0或更高版本 !> 若编译时开启HTTP2,则默认会启用HTTP2协

    • 程序代码 http_server.php $http = new Swoole\Http\Server("0.0.0.0", 9501); $http->on('request', function ($request, $response) { var_dump($request->get, $request->post); $response->header("Content

    • subscribe 方法 client.subscribe(topic, callback[, timeout[, failswitch]]); client.subscribe(topic, id, callback[, timeout[, failswitch]]); subscribe 方法的用处是订阅服务器端的推送服务。该方法有两种方式,一种是自动获取设置客户端 id,另一种是手动设置客