apache / dubbo-go

Go Implementation For Apache Dubbo .
https://dubbo.apache.org/
Apache License 2.0
4.69k stars 917 forks source link

Lightweight HTTP1&2 Protocol to avoid direct depend on grpc-go library. #2263

Open chickenlj opened 1 year ago

chickenlj commented 1 year ago

According to the Dubbo3 architecture, Triple protocol should be defined as a slim HTTP-based protocol for building browser and gRPC-compatible, high-performance web and rpc services.

With the above goal in mind, the Triple implementation in Dubbo-go should be able to do the following:

But the current implementation is still far away or even impossible to meet those requirements. The current implementation depends directly on grpc-go library to fulfill data exchange purpose and is a way proven to have many drawbacks:

So, I think we should provide our lightweight HTTP/2 rpc protocol implementation, and to achieve that, a very similar one provided by Buf Connect Go can be a very good reference to start.

AlexStocks commented 1 year ago

这个工作建议跟李志信沟通下,知道下当年选用 grpc-go 的背景,然后再讨论。

chickenlj commented 1 year ago

这个工作建议跟李志信沟通下,知道下当年选用 grpc-go 的背景,然后再讨论。

Actually, we had a brief discussion and reached the above conclusion. So let's see what others think about it.

pyh4 commented 1 year ago

@chickenlj Hi, there! I am a graduate student in software engineering at Zhejiang University. I have experience in Golang. I have contributed to open source project before and I am interested in this issue.

I have gone through the details and here are my understandings of the issue:

Any further advice and guidance would be appreciated.

106umao commented 1 year ago

I am very interested in this issue and will submit a proposal. I look forward to further communicating with the community about this issue.

DMwangnima commented 1 year ago

Temporary triple design documentation:

Triple-go

设计目标

  1. 在完全兼容Grpc,保证与老应用正常通信的基础上,支持h1和h2下采用curl,浏览器等web方式直接访问服务,无需任何配置
  2. 剥除对grpc-go的依赖,使用net/http
  3. 保持 编写IDL文件->protoc编译自动生成stub代码->实现业务逻辑 的工作模式,stub代码结构与接口向Grpc靠近(暂定)

设计细节

组成

Rest + Grpc,服务端在单端口上同时支持这两种协议,客户端由用户选择调用方式,默认为Grpc

协议区分

统一进入ServeHTTP(responseWriter http.ResponseWriter, request *http.Request)后,

POST/GET? + content-type: application/ -> Rest

POST + content-type: application/grpc -> Grpc

Rest

  1. 额外Header: triple-timeout-ms, triple-version

  2. rpc错误信息: json编码的Error

    type WireError struct {
      Code    Code                 `json:"code"`
      Message string               `json:"message,omitempty"`
      // google.golang.org/genproto/googleapis/rpc/errdetails
      Details []*ErrorDetail       `json:"details,omitempty"`
    }
  3. Triple Error Code与HTTP Code映射:

    switch code {
    case CodeCanceled:
      return 408
    case CodeUnknown:
      return 500
    case CodeInvalidArgument:
      return 400
    case CodeDeadlineExceeded:
      return 408
    case CodeNotFound:
      return 404
    case CodeAlreadyExists:
      return 409
    case CodePermissionDenied:
      return 403
    case CodeResourceExhausted:
      return 429
    case CodeFailedPrecondition:
      return 412
    case CodeAborted:
      return 409
    case CodeOutOfRange:
      return 400
    case CodeUnimplemented:
      return 404
    case CodeInternal:
      return 500
    case CodeUnavailable:
      return 503
    case CodeDataLoss:
      return 500
    case CodeUnauthenticated:
      return 401
  4. GET query params(ignore)

    triple=v1 // 协议版本

    encoding=json //编码方式,等同于content-type

    message=... //编码后的请求参数,还需要经过base64序列化

    compression=gzip //压缩方式,等同于content-encoding

    eg:

    GET /buf.greet.v1.GreetService/Greet?triple=v1&encoding=json&msg=%7B%22name%22%3A%22Buf%22%7D HTTP/1.1 Host: demo.connect.build

    < HTTP/1.1 200 OK < Content-Type: application/json < < {"greeting": "Hello, Buf!"}

  5. 只支持unary,不支持stream

  6. 对于具有幂等性的调用,才支持GET(ignore)

Grpc

  1. 参照https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md进行实现,完全使用net/http
  2. 需要性能测试得出与grpc-go的具体差距
  3. 需要cross-test,triple client -> grpc-go server, grpc-go client -> triple server,可考虑新起一个项目保证triple本身足够轻量

protoc-gen-triple-go

  1. 为了兼容dubbo-go,引入ClientImpl和ProviderBase

    对于用户端,var cli = new(ClientImpl);config.SetConsumerService(cli);config.Load()后直接使用cli即可

    对于服务端,用户编写的struct需要wrap一下ProviderBase

  2. 目前triple-go和protoc-gen-triple-go为泛型版本,需要考虑是否更改为非泛型版本。对于用户来说,除了版本升级问题,接口处的请求参数也需要NewRequest wrap一下。