Azure 中继混合连接协议Azure Relay Hybrid Connections protocol

Azure 中继是 Azure 服务总线平台最重要的功能支柱之一。Azure Relay is one of the key capability pillars of the Azure Service Bus platform. 中继的新“混合连接”功能是基于 HTTP 和 WebSocket 的安全、开放协议演化版。The new Hybrid Connections capability of Relay is a secure, open-protocol evolution based on HTTP and WebSockets. 它取代了之前基于专用协议构建的名为“BizTalk 服务”的功能。It supersedes the former, equally named BizTalk Services feature that was built on a proprietary protocol foundation. 将混合连接集成到 Azure 应用服务并不影响原有的运行方式。The integration of Hybrid Connections into Azure App Services will continue to function as-is.

混合连接在两个联网应用程序之间启用双向二进制流通信和简单的数据报流。Hybrid Connections enables bi-directional, binary stream communication and simple datagram flow between two networked applications. 任何一方或双方均可驻留在 NAT 或防火墙之后。Either or both parties can reside behind NATs or firewalls.

本文介绍如何与混合连接中继的客户端交互,以连接侦听器和发送方角色中的客户端。This article describes the client-side interactions with the Hybrid Connections relay for connecting clients in listener and sender roles. 此外,还介绍侦听器如何接受新的连接和请求。It also describes how listeners accept new connections and requests.

交互模型Interaction model

混合连接中继将通过在 Azure 云中提供双方都可在自身网络中发现并连接到的集合点来连接双方。The Hybrid Connections relay connects two parties by providing a rendezvous point in the Azure cloud that parties can discover and connect to from their own network's perspective. 该集合点就是在本文和其他文档、API 及 Azure 门户中提及的“混合连接”。The rendezvous point is called "Hybrid Connection" in this and other documentation, in the APIs, and also in the Azure portal. 混合连接服务终结点在本文其余部分被称为“服务”。The Hybrid Connections service endpoint is referred to as the "service" for the rest of this article.

该服务允许中继 Web 套接字连接和 HTTP(S) 请求与响应。The service allows for relaying Web Socket connections and HTTP(S) requests and responses.

该交互模型倾向于使用由许多其他网络服务 API 创建的术语:The interaction model leans on the nomenclature established by many other networking APIs. 首先一个是侦听器,指示处理传入连接的准备情况,然后在这些连接到达时进行接受。There is a listener that first indicates readiness to handle incoming connections, and subsequently accepts them as they arrive. 在另一端,某个客户端会连接到侦听器,预期该连接被接受以建立双向通信路径。On the other side, a client connects towards the listener, expecting that connection to be accepted for establishing a bi-directional communication path. “连接”、“侦听”和“接受”与大多数套接字 API 中找到的术语相同。"Connect," "Listen," and "Accept" are the same terms you find in most socket APIs.

任何中继通信模型都会使双方生成针对服务终结点的出站连接。Any relayed communication model has either party making outbound connections towards a service endpoint. 这使得“侦听器”也常被说成“客户端”,可能还会导致其他术语重载。This makes the "listener" also a "client" in colloquial use, and may also cause other terminology overloads. 因此,用于混合连接的准确术语如下:The precise terminology therefore used for Hybrid Connections is as follows:

连接两端上的程序称为“客户端”,因为相对于服务,它们是客户端。The programs on both sides of a connection are called "clients," since they are clients to the service. 等待和接受连接的客户端是“侦听器”,或者称其在“侦听器角色”中。The client that waits for and accepts connections is the "listener," or is said to be in the "listener role." 通过服务向侦听器启动新连接的客户端称为“发送方”,或者称其在“发送方角色”中。The client that initiates a new connection towards a listener via the service is called the "sender," or is in the "sender role."

侦听器交互Listener interactions

侦听器与服务之间存在五种交互,所有通信详细信息都已在本文后续参考部分中予以说明。The listener has five interactions with the service; all wire details are described later in this article in the reference section.

从服务接收“侦听”、“接受”和“请求”消息。The Listen, Accept, and Request messages are received from the service. 侦听器发送“续订”和“Ping”操作。The Renew, and Ping operations are sent by the listener.

侦听消息Listen message

侦听器会创建一个出站 WebSocket 连接,指示对服务的准备情况,即侦听器准备接受连接的情况。To indicate readiness to the service that a listener is ready to accept connections, it creates an outbound WebSocket connection. 连接握手包含中继命名空间所配置的混合连接名称,以及授予对该名称“侦听”权限的安全令牌。The connection handshake carries the name of a Hybrid Connection configured on the Relay namespace, and a security token that confers the "Listen" right on that name.

服务接受 WebSocket 后,注册完成并且建立的 WebSocket 作为“控制通道”保持活动状态,以支持所有后续交互。When the WebSocket is accepted by the service, the registration is complete and the established WebSocket is kept alive as the "control channel" for enabling all subsequent interactions. 对于一个混合连接,服务最多可允许 25 个并行侦听器。The service allows up to 25 concurrent listeners for one Hybrid Connection. AppHooks 的配额待定。The quota for AppHooks is to be determined.

对于混合连接,如果有两个或更多活动的侦听器,则将传入连接以随机顺序均衡分布在这些侦听器上;尽最大努力实现平均分配。For Hybrid Connections, if there are two or more active listeners, incoming connections are balanced across them in random order; fair distribution is attempted with best effort.

接受消息Accept message

发送方打开服务上的新连接时,服务会选择并通知混合连接上活动的侦听器之一。When a sender opens a new connection on the service, the service chooses and notifies one of the active listeners on the Hybrid Connection. 此通知作为 JSON 消息通过打开的控制通道发送到侦听器。This notification is sent to the listener over the open control channel as a JSON message. 该消息包含侦听器为了接受连接而必须连接到的 Web 套接字终结点的 URL。The message contains the URL of the WebSocket endpoint that the listener must connect to for accepting the connection.

该 URL 可以且必须直接由侦听器使用,无需任何额外作业。The URL can and must be used directly by the listener without any extra work. 编码信息仅在短时间内有效,基本上为发送方愿意等待的端到端创建连接的时间。The encoded information is only valid for a short period of time, essentially for as long as the sender is willing to wait for the connection to be established end-to-end. 假设最长时间为 30 秒。The maximum to assume is 30 seconds. 该 URL 只能用于一次成功的连接尝试。The URL can only be used for one successful connection attempt. 使用集合 URL 建立 Web 套接字连接后,该 Web 套接字上的所有后续活动都将与发送方来回中继。As soon as the WebSocket connection with the rendezvous URL is established, all further activity on this WebSocket is relayed from and to the sender. 无需服务进行任何干预或转译即会发生此操作。This happens without any intervention or interpretation by the service.

请求消息Request message

除了 Web 套接字连接以外,侦听器还可以从发送方接收 HTTP 请求帧(如果已对混合连接显式启用此功能)。In addition to WebSocket connections, the listener can also receive HTTP request frames from a sender, if this capability is explicitly enabled on the Hybrid Connection.

附加到混合连接的、支持 HTTP 的侦听器必须处理 request 手势。Listeners that attach to Hybrid Connections with HTTP support MUST handle the request gesture. 不处理 request,因而导致连接时重复出现超时错误的侦听器将来可能会被服务列入阻止列表。A listener that doesn't handle request and therefore causes repeated timeout errors while being connected MAY be blacklisted by the service in the future.

HTTP 帧标头元数据将转换为 JSON,以方便由侦听器框架处理;执行这种转换的另一个原因是,相比 JSON 分析器,HTTP 标头分析库极其少见。HTTP frame header metadata is translated into JSON for simpler handling by the listener framework, also because HTTP header parsing libraries are rarer than JSON parsers. 仅与发送方与中继 HTTP 网关之间的关系相关的 HTTP 元数据(包括授权信息)不会转发。HTTP metadata that is only relevant for the relationship between the sender and the Relay HTTP gateway, including authorization information, is not forwarded. HTTP 请求正文以透明方式作为二进制 Web 套接字帧传输。HTTP request bodies are transparently transferred as binary WebSocket frames.

侦听器可以使用等效的响应手势来响应 HTTP 请求。The listener can respond to HTTP requests using an equivalent response gesture.

请求/响应流默认使用控制通道,但可根据需要“升级”到不同的会合 Web 套接字。The request/response flow uses the control channel by default, but can be "upgraded" to a distinct rendezvous WebSocket whenever required. 不同的 Web 套接字连接会提高每个客户端对话的吞吐量,但它们会增大侦听器需要处理的连接负担,因此不一定适合对轻型客户端使用此方案。Distinct WebSocket connections improve throughput for each client conversation, but they burden the listener with more connections that need to be handled, which may not be desire able for lightweight clients.

在控制通道上,请求和响应正文大小限制为最大 64 kB。On the control channel, request and response bodies are limited to at most 64 kB in size. HTTP 标头元数据限制为总共 32 kB。HTTP header metadata is limited to a total of 32 kB. 如果请求或响应超过该阈值,必须使用与接受处理方法相当的手势,将侦听器升级到会合 Web 套接字。If either the request or the response exceeds that threshold, the listener MUST upgrade to a rendezvous WebSocket using a gesture equivalent to handling the Accept.

对于请求,服务会决定是否通过控制通道来路由请求。For requests, the service decides whether to route requests over the control channel. 这包括但不限于请求完全超过 64 kB(标头和正文)、使用“分块”传输编码发送请求,并且服务有理由预测请求会超过 64 kB,或者读取请求不是即时发生的情况。This includes, but may not be limited to cases where a request exceeds 64 kB (headers plus body) outright, or if the request is sent with "chunked" transfer-encoding and the service has reason to expect for the request to exceed 64kB or reading the request is not instantaneous. 如果服务选择通过会合点传送请求,它只会将会合地址传递给侦听器。If the service chooses to deliver the request over rendezvous, it only passes the rendezvous address to the listener. 然后,侦听器必须建立会合 Web 套接字,并且服务会立即通过会合 Web 套接字传送完整的请求(包括正文)。The listener then MUST establish the rendezvous WebSocket and the service promptly delivers the full request including bodies over the rendezvous WebSocket. 响应也必须使用会合 Web 套接字。The response MUST also use the rendezvous WebSocket.

对于通过控制通道抵达的请求,侦听器会决定是要通过控制通道还是会合点做出响应。For requests that arrive over the control channel, the listener decides whether to respond over the control channel or via rendezvous. 服务必须包含一个会合地址,将在该地址中通过控制通道路由每个请求。The service MUST include a rendezvous address with every request routed over the control channel. 只有在从当前请求升级时,此地址才有效。This address is only valid for upgrading from the current request.

如果侦听器选择升级,则它会建立连接,并立即通过建立的会合套接字传送响应。If the listener chooses to upgrade, it connects and promptly delivers the response over the established rendezvous socket.

建立会合 Web 套接字后,侦听器应保留该 Web 套接字,以便进一步处理来自同一客户端的请求和响应。Once the rendezvous WebSocket has been established, the listener SHOULD maintain it for further handling of requests and responses from the same client. 服务保留 Web 套接字的持续时间与发送方的 HTTPS 套接字连接保持时间相同,会通过保留的 Web 套接字路由来自该发送方的所有后续请求。The service will maintain the WebSocket for as long as the HTTPS socket connection with the sender persists and will route all subsequent requests from that sender over the maintained WebSocket. 如果侦听器选择删除其所在一端的会合 Web 套接字,服务也会删除与发送方之间的连接,不管后续的请求是否已在处理中。If the listener chooses to drop the rendezvous WebSocket from its side, the service will also drop the connection to the sender, irrespective of whether a subsequent request might already be in progress.

续订操作Renew operation

注册侦听器和维护控制通道必须使用的安全令牌可能会在侦听器活动期间到期。The security token that must be used to register the listener and maintain the control channel may expire while the listener is active. 令牌到期不会影响正在进行的连接,但会导致服务在到期时或到期不久后终止控制通道。The token expiry does not affect ongoing connections, but it does cause the control channel to be dropped by the service at or soon after the moment of expiry. “续订”操作是一个 JSON 消息,侦听器可以发送它来替换与控制通道关联的令牌,这样即可延长控制通道的维护时间。The "renew" operation is a JSON message that the listener can send to replace the token associated with the control channel, so that the control channel can be maintained for extended periods.

Ping 操作Ping operation

如果控制通道长时间处于空闲,通道上的中介,例如负载均衡器或 NAT 可能会终止 TCP 连接。If the control channel stays idle for a long time, intermediaries on the way, such as load balancers or NATs may drop the TCP connection. “ping”操作可通过在该通道上发送少量数据,提醒网络路由上的所有人该连接处于活动状态,以此来避免上述终止情况;此操作还可充当侦听器的“实时”测试。The "ping" operation avoids that by sending a small amount of data on the channel that reminds everyone on the network route that the connection is meant to be alive, and it also serves as a "live" test for the listener. 如果 ping 失败,则控制通道应视为不可用,并且侦听器应重新进行连接。If the ping fails, the control channel should be considered unusable and the listener should reconnect.

发送方交互Sender interaction

发送方与服务之间存在两种交互:连接 Web 套接字,或通过 HTTPS 发送请求。The sender has two interactions with the service: it connects a Web Socket or it sends requests via HTTPS. 无法从发送方角色通过 Web 套接字发送请求。Requests cannot be sent over a Web Socket from the sender role.

连接操作Connect operation

“连接”操作会打开服务上的 WebSocket,提供混合连接的名称和(可选,但默认为必需)授予查询字符串中“发送”权限的安全令牌。The "connect" operation opens a WebSocket on the service, providing the name of the Hybrid Connection and (optionally, but required by default) a security token conferring "Send" permission in the query string. 然后,服务会按照之前所述的方式与侦听器进行交互,并且侦听器会创建一个与此 WebSocket 联接的集合连接。The service then interacts with the listener in the way described previously, and the listener creates a rendezvous connection that is joined with this WebSocket. WebSocket 被接受后,该 WebSocket 上的所有后续交互都会使用已连接的侦听器。After the WebSocket has been accepted, all further interactions on that WebSocket are with a connected listener.

请求操作Request operation

对于启用了该功能的混合连接,发送方可以向侦听器发送限制程度极低的 HTTP 请求。For Hybrid Connections for which the feature has been enabled, the sender can send largely unrestricted HTTP requests to listeners.

但嵌入在查询字符串或请求 HTTP 标头中的中继访问令牌除外。对于针对中继地址和中继地址路径中所有后缀执行的所有 HTTP 操作而言,中继是完全透明的,使侦听器能够完全控制端到端授权甚至 CORS 等 HTTP 扩展功能。Except for a Relay access token that is either embedded in the query string or in an HTTP header of the request, the Relay is fully transparent to all HTTP operations on the Relay address and all suffixes of the Relay address path, leaving the listener fully in control of end-to-end authorization and even HTTP extension features like CORS.

对中继终结点的发送方授权默认已启用,但可以选择禁用。Sender authorization with the Relay endpoint is turned on by default, but is OPTIONAL. 混合连接的所有者可以选择允许匿名发送方。The owner of the Hybrid Connection can choose to allow anonymous senders. 服务会截获、检查和剥离授权信息,如下所述:The service will intercept, inspect, and strip authorization information as follows:

  1. 如果查询字符串包含 sb-hc-token 表达式,则始终会从查询字符串中剥离该表达式。If the query string contains a sb-hc-token expression, the expression will ALWAYS be stripped from the query string. 如果已启用中继授权,则会评估该表达式。It will be evaluated if Relay authorization is turned on.
  2. 如果请求标头包含 ServiceBusAuthorization 标头,则始终会从标头集合中剥离标头表达式。If the request headers contain a ServiceBusAuthorization header, the header expression will ALWAYS be stripped from the header collection. 如果已启用中继授权,则会评估该表达式。It will be evaluated if Relay authorization is turned on.
  3. 仅当已启用中继授权、请求标头包含 Authorization 标头并且上述表达式都不存在时,才会评估并剥离标头。Only if Relay authorization is turned on, and if the request headers contain an Authorization header, and neither of the prior expressions is present, the header will be evaluated and stripped. 否则,始终按原样传递 AuthorizationOtherwise, the Authorizationis always passed on as-is.

如果没有活动的侦听器,服务会返回“错误的网关”502 错误代码。If there is no active listener, the service will return a 502 "Bad Gateway" error code. 如果服务似乎未处理请求,则在 60 秒后会返回“网关超时”504 错误代码。If the service does not appear to handle the request, the service will return a 504 "Gateway Timeout" after 60 seconds.

交互摘要Interaction summary

此交互模型的结果是,发送方客户端使用“干净”的 WebSocket(已连接侦听器且无需进一步的“报头”或准备)离开握手。The result of this interaction model is that the sender client comes out of the handshake with a "clean" WebSocket, which is connected to a listener and that needs no further preambles or preparation. 凭借此模型,几乎任何现有 Web 套接字客户端实现通过将正确构造的 URL 提供到其 Web 套接字客户端层,即可立即使用混合连接服务。This model enables practically any existing WebSocket client implementation to readily take advantage of the Hybrid Connections service by supplying a correctly constructed URL into their WebSocket client layer.

侦听器通过接受交互获取的集合连接 WebSocket 同样也是干净的,并且可被传递到任何现有 WebSocket 服务器实现,使用一些最小限度的额外抽象层,区分其框架的本地网络侦听器上的“接受”操作和混合连接远程“接受”操作。The rendezvous connection WebSocket that the listener obtains through the accept interaction is also clean and can be handed to any existing WebSocket server implementation with some minimal extra abstraction that distinguishes between "accept" operations on their framework's local network listeners and Hybrid Connections remote "accept" operations.

HTTP 请求/响应模型为发送方提供受限程度极低的 HTTP 协议外围应用,其中包含可选的授权层。The HTTP request/response model gives the sender a largely unrestricted HTTP protocol surface area with an OPTIONAL authorization layer. 侦听器获取预先分析的 HTTP 请求标头节,可以使用携带 HTTP 正文的二进制帧,将该节转换回到下游 HTTP 请求,或按原样进行处理。The listener gets a pre-parsed HTTP request header section that can be turned back into a downstream HTTP request or handled as is, with binary frames carrying HTTP bodies. 响应使用相同的格式。Responses use the same format. 可以通过与所有发送方共享的单个 Web 套接字,来处理与 64 KB 以下的请求和响应正文的交互。Interactions with less than 64 KB of request and response body can be handled over a single Web Socket that is shared for all senders. 可以使用会合模型处理更大的请求和响应。Larger requests and responses can be handled using the rendezvous model.

协议参考Protocol reference

本部分介绍前述协议交互的详细信息。This section describes the details of the protocol interactions described previously.

所有 WebSocket 连接都作为 HTTPS 1.1 的升级在端口 443 上生成,此操作通常被一些 WebSocket 框架或 API 抽象化。All WebSocket connections are made on port 443 as an upgrade from HTTPS 1.1, which is commonly abstracted by some WebSocket framework or API. 此处的说明保持实现中立,不指示特定框架。The description here is kept implementation neutral, without suggesting a specific framework.

侦听器协议Listener protocol

侦听器协议由两个连接动作和三个消息操作组成。The listener protocol consists of two connection gestures and three message operations.

侦听器控制通道连接Listener control channel connection

控制通道通过创建针对以下内容的 WebSocket 连接打开:The control channel is opened with creating a WebSocket connection to:

wss://{namespace-address}/$hc/{path}?sb-hc-action=...[&sb-hc-id=...]&sb-hc-token=...

namespace-address 是托管混合连接的 Azure 中继命名空间的完全限定域名,通常格式为 {myname}.servicebus.chinacloudapi.cnThe namespace-address is the fully qualified domain name of the Azure Relay namespace that hosts the Hybrid Connection, typically of the form {myname}.servicebus.chinacloudapi.cn.

查询字符串参数选项如下所示。The query string parameter options are as follows.

参数Parameter 必须Required 说明Description
sb-hc-action Yes 对于侦听器角色,该参数必须是 sb-hc-action=listenFor the listener role, the parameter must be sb-hc-action=listen
{path} Yes 要注册该侦听器的预配置混合连接的 URL 编码命名空间路径。The URL-encoded namespace path of the pre-configured Hybrid Connection to register this listener on. 此表达式追加至固定的 $hc/ 路径部分。This expression is appended to the fixed $hc/ path portion.
sb-hc-token 是*Yes* 侦听器必须为命名空间或混合连接提供有效的 URL 编码的服务总线共享访问令牌,以授予“侦听”权限。The listener must provide a valid, URL-encoded Service Bus Shared Access Token for the namespace or Hybrid Connection that confers the Listen right.
sb-hc-id No 该客户端提供的可选 ID 可实现端到端诊断跟踪。This client-supplied optional ID enables end-to-end diagnostic tracing.

如果由于混合连接路径未注册、令牌无效或丢失或其他一些错误,导致 WebSocket 连接失败,则会使用常规的 HTTP 1.1 状态反馈模型提供错误反馈。If the WebSocket connection fails due to the Hybrid Connection path not being registered, or an invalid or missing token, or some other error, the error feedback is provided using the regular HTTP 1.1 status feedback model. 状态说明包含可传达给 Azure 支持人员的错误跟踪 ID:The status description contains an error tracking-id that can be communicated to Azure support personnel:

代码Code 错误Error 说明Description
404404 未找到Not Found 混合连接路径无效或基 URL 格式不正确。The Hybrid Connection path is invalid or the base URL is malformed.
401401 未授权Unauthorized 安全令牌丢失或格式不正确或无效。The security token is missing or malformed or invalid.
403403 禁止Forbidden 安全令牌对此操作的此路径无效。The security token is not valid for this path for this action.
500500 内部错误Internal Error 服务内部出错。Something went wrong in the service.

如果服务在初始设置 WebSocket 连接后有意将其关闭,则会使用相应的 WebSocket 协议错误代码,连同也包含跟踪 ID 的描述性错误消息传达执行此操作的原因。If the WebSocket connection is intentionally shut down by the service after it was initially set up, the reason for doing so is communicated using an appropriate WebSocket protocol error code along with a descriptive error message that also includes a tracking ID. 服务在未出现错误状况的情况下不会关闭控制通道。The service will not shut down the control channel without encountering an error condition. 任何干净关闭都由客户端控制。Any clean shutdown is client controlled.

WS 状态WS Status 说明Description
10011001 混合连接路径已删除或禁用。The Hybrid Connection path has been deleted or disabled.
10081008 安全令牌已到期,因此违背了授权策略。The security token has expired, therefore the authorization policy is violated.
10111011 服务内部出错。Something went wrong in the service.

接受握手Accept handshake

“接受”通知作为 WebSocket 文本框中的 JSON 消息,由服务通过之前建立的控制通道发送到侦听器。The "accept" notification is sent by the service to the listener over the previously established control channel as a JSON message in a WebSocket text frame. 不会对此消息进行任何回复。There is no reply to this message.

该消息包含名为“accept”的 JSON 对象,此时该对象定义以下属性:The message contains a JSON object named "accept", which defines the following properties at this time:

  • address - 用于创建服务的 WebSocket 以接受传入连接的 URL 字符串。address - the URL string to be used for establishing the WebSocket to the service to accept an incoming connection.
  • id - 该连接的唯一标识符。id - the unique identifier for this connection. 如果该 ID 由发送方客户端提供,则是发送方提供的值,否则为系统生成的值。If the ID was supplied by the sender client, it is the sender supplied value, otherwise it is a system generated value.
  • connectHeaders - 发送方向中继终结点提供的所有 HTTP 标头,其中也包括 Sec-WebSocket-Protocol 和 Sec-WebSocket-Extensions 标头。connectHeaders - all HTTP headers that have been supplied to the Relay endpoint by the sender, which also includes the Sec-WebSocket-Protocol and the Sec-WebSocket-Extensions headers.
{
    "accept" : {
        "address" : "wss://dc-node.servicebus.chinacloudapi.cn:443/$hc/{path}?..."
        "id" : "4cb542c3-047a-4d40-a19f-bdc66441e736",
        "connectHeaders" : {
            "Host" : "...",
            "Sec-WebSocket-Protocol" : "...",
            "Sec-WebSocket-Extensions" : "..."
        }
     }
}

侦听器使用 JSON 消息中提供的地址 URL,创建接受或拒绝发送方套接字的 WebSocket。The address URL provided in the JSON message is used by the listener to establish the WebSocket for accepting or rejecting the sender socket.

接受套接字Accepting the socket

若接受,侦听器会创建对已提供地址的 WebSocket 连接。To accept, the listener establishes a WebSocket connection to the provided address.

如果“接受”消息包含 Sec-WebSocket-Protocol 头,则预计只有在侦听器支持该协议时,才会接受 WebSocket。If the "accept" message carries a Sec-WebSocket-Protocol header, it is expected that the listener only accepts the WebSocket if it supports that protocol. 此外,侦听器还应在创建 WebSocket 时设置该头。Additionally, it sets the header as the WebSocket is established.

这同样适用于 Sec-WebSocket-Extensions 头。The same applies to the Sec-WebSocket-Extensions header. 如果框架支持扩展,则框架应针对扩展将头设置为所需 Sec-WebSocket-Extensions 握手的服务器端回复。If the framework supports an extension, it should set the header to the server-side reply of the required Sec-WebSocket-Extensions handshake for the extension.

URL 必须原样使用,用于创建接受套接字,但是要包含以下参数:The URL must be used as-is for establishing the accept socket, but contains the following parameters:

参数Parameter 必须Required 说明Description
sb-hc-action Yes 若要接受套接字,该参数必须为 sb-hc-action=acceptFor accepting a socket, the parameter must be sb-hc-action=accept
{path} Yes (请参阅下文)(see the following paragraph)
sb-hc-id No 请参阅上述的 ID 说明。See previous description of id.

{path} 是要注册此侦听器的预配置混合连接的 URL 编码命名空间路径。{path} is the URL-encoded namespace path of the preconfigured Hybrid Connection on which to register this listener. 此表达式追加至固定的 $hc/ 路径部分。This expression is appended to the fixed $hc/ path portion.

path 表达式可以使用后缀和查询字符串表达式进行扩展,该表达式在分隔正斜杠之后追加注册名称。The path expression may be extended with a suffix and a query string expression that follows the registered name after a separating forward slash. 这样,发送方客户端就可以在无法包含 HTTP 头时将调度参数传递到接受侦听器。This enables the sender client to pass dispatch arguments to the accepting listener when it is not possible to include HTTP headers. 侦听器框架可从路径中分析出固定路径部分和注册名称,并向应用程序提供其余部分(可能不含任何带 sb- 前缀的查询字符串参数),以决定是否接受连接。The expectation is that the listener framework parses out the fixed path portion and the registered name from the path and makes the remainder, possibly without any query string arguments prefixed by sb-, available to the application for deciding whether to accept the connection.

有关详细信息,请参阅后面的“发送方协议”部分。For more information, see the following "Sender Protocol" section.

如果出现错误,服务可能会提供以下回复:If there is an error, the service can reply as follows:

代码Code 错误Error 说明Description
403403 禁止Forbidden 此 URL 无效。The URL is not valid.
500500 内部错误Internal Error 服务内部出错Something went wrong in the service

建立连接后,服务器会在发送方 WebSocket 关闭后或在以下状态下关闭 WebSocket:After the connection has been established, the server shuts down the WebSocket when the sender WebSocket shuts down, or with the following status:

WS 状态WS Status 说明Description
10011001 发送方客户端关闭连接。The sender client shuts down the connection.
10011001 混合连接路径已删除或禁用。The Hybrid Connection path has been deleted or disabled.
10081008 安全令牌已到期,因此违背了授权策略。The security token has expired, therefore the authorization policy is violated.
10111011 服务内部出错。Something went wrong in the service.
拒绝套接字Rejecting the socket

在检查 accept 消息后拒绝套接字,将需要一个相似的握手,以使传达拒绝原因的状态代码和状态说明可以返回至发送方。Rejecting the socket after inspecting the accept message requires a similar handshake so that the status code and status description communicating the reason for the rejection can flow back to the sender.

此处的协议设计选项是使用 WebSocket 握手(用于在定义的错误状态下结束),以便侦听器客户端实现可以继续依赖 WebSocket 客户端,而无需使用其他的裸 HTTP 客户端。The protocol design choice here is to use a WebSocket handshake (that is designed to end in a defined error state) so that listener client implementations can continue to rely on a WebSocket client and do not need to employ an extra, bare HTTP client.

若要拒绝套接字,客户端需使用 accept 消息中的地址 URI 并将两个查询字符串参数追加到其中,如下所示:To reject the socket, the client takes the address URI from the accept message and appends two query string parameters to it, as follows:

ParamParam 必须Required 说明Description
sb-hc-statusCodesb-hc-statusCode Yes 数值型 HTTP 状态代码。Numeric HTTP status code.
sb-hc-statusDescriptionsb-hc-statusDescription Yes 可人工读取的拒绝原因。Human readable reason for the rejection.

然后使用生成的 URI 建立 WebSocket 连接。The resulting URI is then used to establish a WebSocket connection.

正确完成后,该握手会有意失败,并出现 HTTP 错误代码 410,因为尚未创建任何 WebSocket。When completing correctly, this handshake intentionally fails with an HTTP error code 410, since no WebSocket has been established. 如果出现问题,会使用以下代码描述问题:If something goes wrong, the following codes describe the error:

代码Code 错误Error 说明Description
403403 禁止Forbidden 此 URL 无效。The URL is not valid.
500500 内部错误Internal Error 服务内部出错。Something went wrong in the service.

请求消息Request message

服务通过控制通道将 request 消息发送到侦听器。The request message is sent by the service to the listener over the control channel. 也可以通过建立的会合 Web 套接字发送同一消息。The same message is also sent over the rendezvous WebSocket once established.

request 由两个部分组成:标头和二进制正文帧。The request consists of two parts: a header and binary body frame(s). 如果没有正文,则会省略正文帧。If there is no body, the body frames are omitted. 请求消息中的布尔值 body 属性指示是否存在正文。The indicator for whether a body is present is the boolean body property in the request message.

对于包含请求正文的请求,结构可能如下所示:For a request with a request body, the structure may look like this:

----- Web Socket text frame ----
{
    "request" :
    {
        "body" : true,
        ...
    }
}
----- Web Socket binary frame ----
FEFEFEFEFEFEFEFEFEFEF...
----- Web Socket binary frame ----
FEFEFEFEFEFEFEFEFEFEF...
----- Web Socket binary frame -FIN
FEFEFEFEFEFEFEFEFEFEF...
----------------------------------

侦听器必须处理拆分到多个二进制帧之间的请求正文的接收(请参阅 Web 套接字片段)。The listener MUST handle receiving the request body split across multiple binary frames (see WebSocket fragments). 收到设置了 FIN 标志的二进制帧时,请求结束。The request ends when a binary frame with the FIN flag set has been received.

对于不包含正文的请求,只有一个文本帧。For a request without a body, there's only one text frame.

----- Web Socket text frame ----
{
    "request" :
    {
        "body" : false,
        ...
    }
}
----------------------------------

request 的 JSON 内容如下:The JSON content for request is as follows:

  • address - URI 字符串。address - URI string. 这是用于此请求的会合地址。This is the rendezvous address to use for this request. 如果传入的请求大于 64 kB,则此消息的余下部分将会留空,并且客户端必须启动等同于如下所述 accept 操作的会合握手。If the incoming request is larger than 64 kB, the remainder of this message is left empty, and the client MUST initiate a rendezvous handshake equivalent to the accept operation described below. 然后,服务将在建立的 Web 套接字放置完整的 requestThe service will then put the complete request on the established Web socket. 如果响应预期可能超过 64 kB,则侦听器也必须启动会合握手,然后通过建立的 Web 套接字传输响应。If the response can be expected to exceed 64 kB, the listener MUST also initiate a rendezvous handshake, and then transfer the response over the established Web socket.

  • id - 字符串。id - string. 此请求的唯一标识符。The unique identifier for this request.

  • requestHeaders - 此对象包含由发送方提供给终结点的所有 HTTP 标头(上面所述的授权信息除外),以及与网关连接严格相关的标头。requestHeaders - this object contains all HTTP headers that have been supplied to the endpoint by the sender, with exception of authorization information as explained above, and headers that strictly relate to the connection with the gateway. 具体而言,在 RFC7230 中定义或保留的所有标头(Via 除外)都会被剥离,而不会转发:Specifically, ALL headers defined or reserved in RFC7230, except Via, are stripped and not forwarded:

    • Connection(RFC7230 第 6.1 部分)Connection (RFC7230, Section 6.1)
    • Content-Length(RFC7230 第 3.3.2 部分)Content-Length (RFC7230, Section 3.3.2)
    • Host(RFC7230 第 5.4 部分)Host (RFC7230, Section 5.4)
    • TE(RFC7230 第 4.3 部分)TE (RFC7230, Section 4.3)
    • Trailer(RFC7230 第 4.4 部分)Trailer (RFC7230, Section 4.4)
    • Transfer-Encoding(RFC7230 第 3.3.1 部分)Transfer-Encoding (RFC7230, Section 3.3.1)
    • Upgrade(RFC7230 第 6.7 部分)Upgrade (RFC7230, Section 6.7)
    • Close(RFC7230 第 8.1 部分)Close (RFC7230, Section 8.1)
  • requestTarget - 字符串。requestTarget - string. 此属性保存请求的“请求目标”(RFC7230 第 5.3 部分)This property holds the "Request Target" (RFC7230, Section 5.3) of the request. 这包括查询字符串部分,其所有 sb-hc- 前缀参数已剥离。This includes the query string portion, which is stripped of ALL sb-hc- prefixed parameters.

  • method - 字符串。method - string. 这是 RFC7231 第 4 部分所述的请求方法。This is the method of the request, per RFC7231, Section 4. 不得使用 CONNECT 方法。The CONNECT method MUST NOT be used.

  • body - 布尔值。body - boolean. 指示是否后接一个或多个二进制正文帧。Indicates whether one or more binary body frame follows.

{
    "request" : {
        "address" : "wss://dc-node.servicebus.chinacloudapi.cn:443/$hc/{path}?...",
        "id" : "42c34cb5-7a04-4d40-a19f-bdc66441e736",
        "requestTarget" : "/abc/def?myarg=value&otherarg=...",
        "method" : "GET",
        "requestHeaders" : {
            "Host" : "...",
            "Content-Type" : "...",
            "User-Agent" : "..."
        },
        "body" : true
     }
}
响应请求Responding to requests

接收方必须做出响应。The receiver MUST respond. 在保持连接期间一直不响应请求可能导致侦听器被列入阻止列表。Repeated failure to respond to requests while maintaining the connection might result in the listener getting blacklisted.

响应可按任意顺序发送,但必须在 60 秒内响应每个请求,否则会将传送报告为失败。Responses may be sent in any order, but each request must be responded to within 60 seconds or the delivery will be reported as having failed. 在服务收到 response 帧之前,会进行 60 秒倒计时。The 60-second deadline is counted until the response frame has been received by the service. 包含多个二进制帧的处理中响应不能空闲 60 秒以上,否则会将其终止。An ongoing response with multiple binary frames cannot become idle for more than 60 seconds or it is terminated.

如果通过控制通道收到了请求,则必须在控制通道上从收到请求的位置发送响应,否则,必须通过会合通道发送响应。If the request is received over the control channel, the response MUST either be sent on the control channel from where the request was received or it MUST be sent over a rendezvous channel.

响应是名为“response”的 JSON 对象。The response is a JSON object named "response". 正文内容的处理规则与 request 消息的处理方式相同,并基于 body 属性。The rules for handling body content are exactly like with the request message and based on the body property.

  • requestId - 字符串。requestId - string. 必需。REQUIRED. 正在响应的 request 消息的 id 属性值。The id property value of the request message being responded to.
  • statusCode - 数字。statusCode - number. 必需。REQUIRED. 指示通知结果的数字 HTTP 状态代码。a numerical HTTP status code that indicates the outcome of the notification. 允许 RFC7231 第 6 部分所述的所有状态代码,但 502“错误的网关”504“网关超时”除外。All status codes of RFC7231, Section 6 are permitted, except for 502 "Bad Gateway" and 504 "Gateway Timeout".
  • statusDescription - 字符串。statusDescription - string. 可选。OPTIONAL. RFC7230 第 3.1.2 部分所述的 HTTP 状态代码原因短语HTTP status-code reason phrase per RFC7230, Section 3.1.2
  • responseHeaders - 要在外部 HTTP 回复中设置的 HTTP 标头。responseHeaders - HTTP headers to be set in an external HTTP reply. request 一样,不得使用 RFC7230 定义的标头。As with the request, RFC7230 defined headers MUST NOT be used.
  • body - 布尔值。body - boolean. 指示是否后接二进制正文帧。Indicates whether binary body frame(s) follow(s).
----- Web Socket text frame ----
{
    "response" : {
        "requestId" : "42c34cb5-7a04-4d40-a19f-bdc66441e736",
        "statusCode" : "200",
        "responseHeaders" : {
            "Content-Type" : "application/json",
            "Content-Encoding" : "gzip"
        }
         "body" : true
     }
}
----- Web Socket binary frame -FIN
{ "hey" : "mydata" }
----------------------------------
通过会合点响应Responding via rendezvous

对于超过 64 kB 的响应,必须通过会合套接字传送响应。For responses that exceed 64 kB, the response MUST be delivered over a rendezvous socket. 此外,如果请求超过 64 kB,并 request 仅包含地址字段,则必须建立会合套接字以获取 requestAlso, if the request exceeds 64 kB, and the request only contains the address field, a rendezvous socket must be established to obtain the request. 建立会合套接字后,必须通过持久保留的会合套接字传送对该相应客户端的响应,以及来自该相应客户端的后续请求。Once a rendezvous socket has been established, responses to the respective client and subsequent requests from that respective client MUST be delivered over the rendezvous socket while it persists.

request 中的 address URL 必须原样使用,用于建立会合套接字,但要包含以下参数:The address URL in the request must be used as-is for establishing the rendezvous socket, but contains the following parameters:

参数Parameter 必须Required 说明Description
sb-hc-action Yes 若要接受套接字,该参数必须为 sb-hc-action=requestFor accepting a socket, the parameter must be sb-hc-action=request

如果出现错误,服务可能会提供以下回复:If there is an error, the service can reply as follows:

代码Code 错误Error 说明Description
400400 请求无效Invalid Request 无法识别的操作,或 URL 无效。Unrecognized action or URL not valid.
403403 禁止Forbidden URL 已过期。The URL has expired.
500500 内部错误Internal Error 服务内部出错Something went wrong in the service

建立连接后,服务器会在客户端的 HTTP 套接字关闭后或处于以下状态时关闭 Web 套接字:After the connection has been established, the server shuts down the WebSocket when the client's HTTP socket shuts down, or with the following status:

WS 状态WS Status 说明Description
10011001 发送方客户端关闭连接。The sender client shuts down the connection.
10011001 混合连接路径已删除或禁用。The Hybrid Connection path has been deleted or disabled.
10081008 安全令牌已到期,因此违背了授权策略。The security token has expired, therefore the authorization policy is violated.
10111011 服务内部出错。Something went wrong in the service.

侦听器令牌续订Listener token renewal

侦听器令牌即将到期时,可以通过已创建的控制通道向服务发送文本框消息来替换令牌。When the listener token is about to expire, it can replace it by sending a text frame message to the service via the established control channel. 消息包含名为 renewToken 的 JSON 对象,此时该对象定义以下属性:The message contains a JSON object called renewToken, which defines the following property at this time:

  • token - 命名空间或混合连接的有效 URL 编码服务总线共享访问令牌,可授予“侦听”权限。token - a valid, URL-encoded Service Bus Shared Access token for the namespace or Hybrid Connection that confers the Listen right.
{
  "renewToken": {
    "token":
      "SharedAccessSignature sr=http%3a%2f%2fcontoso.servicebus.chinacloudapi.cn%2fhyco%2f&sig=XXXXXXXXXX%3d&se=1471633754&skn=SasKeyName"
  }
}

如果令牌验证失败,访问被拒绝,则云服务会关闭控制通道 WebSocket 并显示错误。If the token validation fails, access is denied, and the cloud service closes the control channel WebSocket with an error. 否则,不会有任何回复。Otherwise there is no reply.

WS 状态WS Status 说明Description
10081008 安全令牌已到期,因此违背了授权策略。The security token has expired, therefore the authorization policy is violated.

Web 套接字连接协议Web Socket connect protocol

发送方协议实际上与创建侦听器的方式相同。The sender protocol is effectively identical to the way a listener is established. 其目标在于对端到端 WebSocket 实现最大透明度。The goal is maximum transparency for the end-to-end WebSocket. 要连接到的地址与侦听器的相同,但是“操作”不同且令牌需要不同的权限:The address to connect to is the same as for the listener, but the "action" differs and the token needs a different permission:

wss://{namespace-address}/$hc/{path}?sb-hc-action=...&sb-hc-id=...&sbc-hc-token=...

namespace-address 是托管混合连接的 Azure 中继命名空间的完全限定域名,通常格式为 {myname}.servicebus.chinacloudapi.cnThe namespace-address is the fully qualified domain name of the Azure Relay namespace that hosts the Hybrid Connection, typically of the form {myname}.servicebus.chinacloudapi.cn.

请求可以包含任意其他 HTTP 头,包括应用程序定义的头。The request can contain arbitrary extra HTTP headers, including application-defined ones. 所有提供的头均流向侦听器并且可在 accept 控制消息的 connectHeader 对象上找到。All supplied headers flow to the listener and can be found on the connectHeader object of the accept control message.

查询字符串参数选项如下所示:The query string parameter options are as follows:

ParamParam 必需?Required? 说明Description
sb-hc-action Yes 对于发送方角色,该参数必须是 sb-hc-action=connectFor the sender role, the parameter must be sb-hc-action=connect.
{path} Yes (请参阅下文)(see the following paragraph)
sb-hc-token 是*Yes* 侦听器必须为命名空间或混合连接提供有效的 URL 编码的服务总线共享访问令牌,以授予“发送”权限。The listener must provide a valid, URL-encoded Service Bus Shared Access Token for the namespace or Hybrid Connection that confers the Send right.
sb-hc-id No 启用端到端诊断跟踪的可选 ID,在接受握手期间会将其提供至侦听器。An optional ID that enables end-to-end diagnostic tracing and is made available to the listener during the accept handshake.

{path} 是要注册此侦听器的预配置混合连接的 URL 编码命名空间路径。The {path} is the URL-encoded namespace path of the preconfigured Hybrid Connection on which to register this listener. path 表达式可以使用后缀和查询字符串表达式进行扩展,以供进一步通信。The path expression can be extended with a suffix and a query string expression to communicate further. 如果混合连接注册在路径 hyco 下,则 path 表达式可以是 hyco/suffix?param=value&...,后跟此处定义的查询字符串参数。If the Hybrid Connection is registered under the path hyco, the path expression can be hyco/suffix?param=value&... followed by the query string parameters defined here. 完整的表达式可能如下所示:A complete expression may then be as follows:

wss://{namespace-address}/$hc/hyco/suffix?param=value&sb-hc-action=...[&sb-hc-id=...&]sbc-hc-token=...

path 表达式传递到“accept”控制消息所含地址 URI 中的侦听器。The path expression is passed through to the listener in the address URI contained in the "accept" control message.

如果由于混合连接路径未注册、令牌无效或丢失或其他一些错误,导致 WebSocket 连接失败,则会使用常规的 HTTP 1.1 状态反馈模型提供错误反馈。If the WebSocket connection fails due to the Hybrid Connection path not being registered, an invalid or missing token, or some other error, the error feedback is provided using the regular HTTP 1.1 status feedback model. 状态说明包含可传达给 Azure 支持人员的错误跟踪 ID:The status description contains an error tracking ID that can be communicated to Azure support personnel:

代码Code 错误Error 说明Description
404404 未找到Not Found 混合连接路径无效或基 URL 格式不正确。The Hybrid Connection path is invalid or the base URL is malformed.
401401 未授权Unauthorized 安全令牌丢失或格式不正确或无效。The security token is missing or malformed or invalid.
403403 禁止Forbidden 安全令牌对此路径和此操作无效。The security token is not valid for this path and for this action.
500500 内部错误Internal Error 服务内部出错。Something went wrong in the service.

如果服务在初始设置 WebSocket 连接后有意将其关闭,则会使用相应的 WebSocket 协议错误代码,连同也包含跟踪 ID 的描述性错误消息传达执行此操作的原因。If the WebSocket connection is intentionally shut down by the service after it has been initially set up, the reason for doing so is communicated using an appropriate WebSocket protocol error code along with a descriptive error message that also includes a tracking ID.

WS 状态WS Status 说明Description
10001000 侦听器关闭套接字。The listener shut down the socket.
10011001 混合连接路径已删除或禁用。The Hybrid Connection path has been deleted or disabled.
10081008 安全令牌已到期,因此违背了授权策略。The security token has expired, therefore the authorization policy is violated.
10111011 服务内部出错。Something went wrong in the service.

HTTP 请求协议HTTP request protocol

HTTP 请求协议允许任意 HTTP 请求,但协议升级除外。The HTTP request protocol allows arbitrary HTTP requests, except protocol upgrades. HTTP 请求指向实体的常规运行时地址,不包括用于混合连接 Web 套接字客户端的 $hc 中缀。HTTP requests are pointed at the entity's regular runtime address, without the $hc infix that is used for hybrid connections WebSocket clients.

https://{namespace-address}/{path}?sbc-hc-token=...

namespace-address 是托管混合连接的 Azure 中继命名空间的完全限定域名,通常格式为 {myname}.servicebus.chinacloudapi.cnThe namespace-address is the fully qualified domain name of the Azure Relay namespace that hosts the Hybrid Connection, typically of the form {myname}.servicebus.chinacloudapi.cn.

请求可以包含任意其他 HTTP 头,包括应用程序定义的头。The request can contain arbitrary extra HTTP headers, including application-defined ones. 提供的所有标头(RFC7230 中直接定义的标头除外,请参阅[请求消息](#Request message))均流向侦听器并可在请求消息的 requestHeader 对象上找到。All supplied headers, except those directly defined in RFC7230 (see [request message](#Request message)) flow to the listener and can be found on the requestHeader object of the request message.

查询字符串参数选项如下所示:The query string parameter options are as follows:

ParamParam 必需?Required? 说明Description
sb-hc-token 是*Yes* 侦听器必须为命名空间或混合连接提供有效的 URL 编码的服务总线共享访问令牌,以授予“发送”权限。The listener must provide a valid, URL-encoded Service Bus Shared Access Token for the namespace or Hybrid Connection that confers the Send right.

也可以在 ServiceBusAuthorizationAuthorization HTTP 标头中携带该令牌。The token can also be carried in either the ServiceBusAuthorization or Authorization HTTP header. 如果混合连接配置为允许匿名请求,则可以省略该令牌。The token can be omitted if the Hybrid Connection is configured to permit anonymous requests.

由于服务实际上充当代理,因此,即使它不是真正的 HTTP 代理,也会添加 Via 标头,或批注符合 RFC7230 第 5.7.1 部分的现有 Via 标头。Because the service effectively acts as a proxy, even if not as a true HTTP proxy, it either adds a Via header or annotates the existing Via header compliant with RFC7230, Section 5.7.1. 服务将中继命名空间主机名添加到 ViaThe service adds the Relay namespace hostname to Via.

代码Code MessageMessage 说明Description
200200 OKOK 请求已至少由一个侦听器处理。The request has been handled by at least one listener.
202202 已接受Accepted 请求已至少由一个侦听器接受。The request has been accepted by at least one listener.

如果出现错误,服务可能会提供以下回复。If there is an error, the service can reply as follows. 可以通过 Via 标头的存在状态来判断响应是来自服务还是侦听器。Whether the response originates from the service or from the listener can be identified through presence of the Via header. 如果存在该标头,则响应来自侦听器。If the header is present, the response is from the listener.

代码Code 错误Error 说明Description
404404 未找到Not Found 混合连接路径无效或基 URL 格式不正确。The Hybrid Connection path is invalid or the base URL is malformed.
401401 未授权Unauthorized 安全令牌丢失或格式不正确或无效。The security token is missing or malformed or invalid.
403403 禁止Forbidden 安全令牌对此路径和此操作无效。The security token is not valid for this path and for this action.
500500 内部错误Internal Error 服务内部出错。Something went wrong in the service.
503503 错误的网关Bad Gateway 无法将请求路由到任何侦听器。The request could not be routed to any listener.
504504 网关超时Gateway Timeout 请求已路由到侦听器,但侦听器在所需的时限内未确认接收。The request was routed to a listener, but the listener did not acknowledge receipt in the required time.

后续步骤Next steps