Attention: The feature described in this doc is still under development or is in a very early stage, please keep updated!
The design of the Triple protocol references various protocol patterns such as gRPC, gRPC-Web, and general HTTP, absorbing the characteristics and advantages of each, ultimately designing a protocol that is easy to access via browsers, fully compatible with gRPC, and supports Streaming communication. Triple can run simultaneously over HTTP/1 and HTTP/2 protocols.
The design goals of the Triple protocol are as follows:
When used with Protocol Buffers (i.e., using IDL to define services), the Triple protocol supports unary, client-streaming, server-streaming, and bi-streaming RPC communication modes, supporting both binary Protobuf and JSON data format payloads. The Triple implementation does not bind to Protocol Buffers; for instance, you can use Java interface to define services, and the Triple protocol has extended Content-Type support for this model.
Taking HTTP/1 request as an example, the current HTTP/1 protocol only supports Unary RPC, supporting application/proto and application/json encoding types, maintaining a usage style consistent with REST-style requests, while the response also includes standard HTTP response encoding (such as 200 OK).
> POST /org.apache.dubbo.demo.GreetService/Greet HTTP/1.1
> Host: 127.0.0.1:30551
> Content-Type: application/json
>
> ["Dubbo"]
< HTTP/1.1 200 OK
< Content-Type: application/json
<
< {"greeting": "Hello, Dubbo!"}
A call request with a specified timeout.
> POST /org.apache.dubbo.demo.GreetService/Greet HTTP/1.1
> Host: 127.0.0.1:30551
> Content-Type: application/json
> Rest-service-timeout: 5000
>
> ["Dubbo"]
< HTTP/1.1 200 OK
< Content-Type: application/json
<
< {"greeting": "Hello, Buf!"}
Currently only POST request type is supported; we will consider supporting GET request types in the future, which may apply to certain service calls with idempotent properties.
Triple only supports Streaming RPC on HTTP/2. To maintain compatibility with gRPC, the Triple implementation on HTTP/2 (including Streaming RPC) is entirely consistent with the standard gRPC protocol.
Request
HEADERS (flags = END_HEADERS)
:method = POST
:scheme = http
:path = /google.pubsub.v2.PublisherService/CreateTopic
:authority = pubsub.googleapis.com
grpc-timeout = 1S
content-type = application/grpc+proto
grpc-encoding = gzip
authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v
DATA (flags = END_STREAM)
<Length-Prefixed Message>
Response
HEADERS (flags = END_HEADERS)
:status = 200
grpc-encoding = gzip
content-type = application/grpc+proto
DATA
<Length-Prefixed Message>
HEADERS (flags = END_STREAM, END_HEADERS)
grpc-status = 0 # OK
trace-proto-bin = jher831yy13JHy3hc
The Triple protocol supports running simultaneously over both HTTP/1 and HTTP/2, comprising the following two parts:
Most RPC calls are unary (request-response), and the Triple HTTP RPC protocol’s unary mode meets the data transmission needs among backend services well. It also addresses the pain points of the gRPC protocol, making it easier for browsers, cURL, and other HTTP tools to access backend services without relying on proxies and gRPC-web, using standard HTTP protocol to initiate calls directly.
Triple HTTP RPC supports both HTTP/1 and HTTP/2 as underlying transport layer protocols, corresponding to supported content-type types as application/json, application/proto.
The Triple protocol request only supports POST requests, with the request path being interfaceName/methodName. To implement a call timeout mechanism, tri-service-timeout (in ms) needs to be added,
The Dubbo framework supports service isolation mechanisms based on group and version, thus the Triple protocol introduces tri-service-group and tri-service-version support.
Request-Headers are sent in the form of standard HTTP headers. If too many headers are received, the server can return the corresponding error message.
TRI-Protocol-Version header is used to distinguish between Triple protocol requests with the same Content-Type and other protocol requests because the application/json format Content-Type is very common. All Dubbo native client implementations should carry TRI-Protocol-Version in the request, and the Dubbo server or proxy can choose to reject requests without TRI-Protocol-Version and return Http-Status 400 error.
If the Server does not support the specified encoding format of Message-Codec, it must return standard HTTP 415 encoding to indicate Unsupported Media Type exception.
Bare-Message is the encoding format of the request payload that depends on the Message-Codec setting:
If Content-Encoding specifies the corresponding value, the payload is compressed and should be decompressed before parsing the encoded data. Bare-Message will be transmitted as the HTTP Body in the link.
POST /org.apache.dubbo.demo.GreetService/Greet HTTP/1.1
Host: 127.0.0.1:30551
Content-Type: application/json
Accept: application/json
Content-Length: 11
Accept-Encoding: compress, gzip
tri-protocol-version: 1.0.0
tri-service-version: 1.0.0
tri-service-group: dubbo
tri-service-timeout: 3000
[{"world"}]
For a successful Response, the HTTP-Status is 200. In this case, the Content-Type of the response body will match the Content-Type of the request body. Bare-Message is the Payload of the RPC response encoded by the method specified by Content-Type and compressed by Content-Encoding (if specified). Bare-Message is sent as the HTTP response body.
For an exception Response, the HTTP-Status is non-200, and they are all standard HTTP status codes. In this case, Content-Type must be “application/json”. Bare-Message can be empty, and if Bare-Message has a value, it must be in standard JSON format data, and if Content-Encoding is specified, it is compressed data, sent back to the caller as the standard HTTP response body. The client can refer to the following table to query the mapping relationship between HTTP-Status and RPC status to understand the specific RPC error situation.
** Successful Response **
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 11
hello world
** Failed Response **
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 46
{"status":20,"message":"request format error"}
Dubbo Error Codes Reference
status http-status message
20 200 ok
25 400 serialization error
30 408 client side timeout
31 408 server side timeout
35 500 channel inactive, directly return the unfinished requests
40 400 request format error
50 500 response format error
60 404 service not found.
70 500 service error
80 500 internal server error
90 500 internal client error
Connect’s HTTP to Error Code Reference
HTTP Status Inferred Code 400 Bad Request invalid_argument 401 Unauthorized unauthenticated 403 Forbidden permission_denied 404 Not Found unimplemented 408 Request Timeout deadline_exceeded 409 Conflict aborted 412 Precondition Failed failed_precondition 413 Payload Too Large resource_exhausted 415 Unsupported Media Type internal 429 Too Many Requests unavailable 431 Request Header Fields Too Large resource_exhausted 502 Bad Gateway unavailable 503 Service Unavailable unavailable 504 Gateway Timeout unavailable all others unknown
The Streaming request processing of the Triple protocol fully follows the gRPC protocol specification and only supports HTTP/2 as the transport protocol. Additionally, Unary requests between backend services default to use the extended gRPC protocol.
The content-type types supported by Triple are standard gRPC types, including application/grpc, application/grpc+proto, application/grpc+json. Furthermore, the implementation of Triple has also extended the application/triple+wrapper encoding format.
The following is the general sequence of message atoms in a gRPC request & response message stream
Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
This is the extended version of the gRPC protocol for Triple. For more detailed specifications, please refer to gRPC Protocol Specification.