连接
Connect是一个纤细的库,用于构建与浏览器和gRPC兼容的HTTP APIs。你可以写一个简短的协议缓冲区模式并实现你的应用逻辑,Connect会生成代码来处理数据采集、路由、压缩和内容类型协商。它还会生成一个习惯性的、类型安全的客户端。处理程序和客户端支持三种协议:gRPC、gRPC-Web和Connect自己的协议。
Connect协议是一个简单的、仅有POST的协议,可以通过HTTP/1.1或HTTP/2工作。它吸收了gRPC和gRPC-Web的最佳部分,包括流媒体,并将它们打包成一个协议,在浏览器、单体和微服务中同样适用。调用Connect API就像使用curl 一样简单。用我们的现场演示试试吧。
curl \
--header "Content-Type: application/json" \
--data '{"sentence": "I feel happy."}' \
https://demo.connect.build/buf.connect.demo.eliza.v1.ElizaService/Say
处理程序和客户端也支持gRPC和gRPC-Web协议,包括流媒体、报头、拖车和错误细节。gRPC兼容的服务器反射和健康检查可以作为独立的软件包提供。我们可以用grpcurl ,而不是cURL,来调用我们的API。
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
grpcurl \
-d '{"sentence": "I feel happy."}' \
demo.connect.build:443 \
buf.connect.demo.eliza.v1.ElizaService/Say
在引擎盖下,Connect只是协议缓冲区和标准库:没有自定义的HTTP实现,没有新的名称解析或负载平衡API,也没有任何惊喜。你已经知道的关于net/http 的一切仍然适用,任何与http.Server 、http.Client 、或http.Handler 一起工作的包也可以与Connect一起工作。
关于Connect的更多信息,请参见公告博文、connect.build的文档(尤其是Go的入门指南)、演示服务或协议规范。
一个小例子
很好奇这一切在实践中是什么样子的?从Protobuf模式中,我们生成一个小型的RPC包。使用该包,我们可以建立一个服务器:
package main
import (
"context"
"log"
"net/http"
"github.com/bufbuild/connect-go"
pingv1 "github.com/bufbuild/connect-go/internal/gen/connect/ping/v1"
"github.com/bufbuild/connect-go/internal/gen/connect/ping/v1/pingv1connect"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
type PingServer struct {
pingv1connect.UnimplementedPingServiceHandler // returns errors from all methods
}
func (ps *PingServer) Ping(
ctx context.Context,
req *connect.Request[pingv1.PingRequest],
) (*connect.Response[pingv1.PingResponse], error) {
// connect.Request and connect.Response give you direct access to headers and
// trailers. No context-based nonsense!
log.Println(req.Header().Get("Some-Header"))
res := connect.NewResponse(&pingv1.PingResponse{
// req.Msg is a strongly-typed *pingv1.PingRequest, so we can access its
// fields without type assertions.
Number: req.Msg.Number,
})
res.Header().Set("Some-Other-Header", "hello!")
return res, nil
}
func main() {
mux := http.NewServeMux()
// The generated constructors return a path and a plain net/http
// handler.
mux.Handle(pingv1connect.NewPingServiceHandler(&PingServer{}))
err := http.ListenAndServe(
"localhost:8080",
// For gRPC clients, it's convenient to support HTTP/2 without TLS. You can
// avoid x/net/http2 by using http.ListenAndServeTLS.
h2c.NewHandler(mux, &http2.Server{}),
)
log.Fatalf("listen failed: %v", err)
}
在服务器运行时,你可以用任何gRPC或Connect客户端发出请求。使用connect-go 来编写一个客户端:
package main
import (
"context"
"log"
"net/http"
"github.com/bufbuild/connect-go"
pingv1 "github.com/bufbuild/connect-go/internal/gen/connect/ping/v1"
"github.com/bufbuild/connect-go/internal/gen/connect/ping/v1/pingv1connect"
)
func main() {
client := pingv1connect.NewPingServiceClient(
http.DefaultClient,
"http://localhost:8080/",
)
req := connect.NewRequest(&pingv1.PingRequest{
Number: 42,
})
req.Header().Set("Some-Header", "hello from connect")
res, err := client.Ping(context.Background(), req)
if err != nil {
log.Fatalln(err)
}
log.Println(res.Msg)
log.Println(res.Header().Get("Some-Other-Header"))
}
当然,http.ListenAndServe 和http.DefaultClient 并不适合生产使用!请参阅Connect的部署文档,了解配置超时、连接池、可观察性和h2c的指南。
生态系统
- connect-grpchealth-go: 兼容gRPC的健康检查
- connect-grpcreflect-go:兼容gRPC的服务器反射
- connect-demo:支持demo.connect.build的示范服务,包括bidi流。
- connect-crosstest:gRPC和gRPC-Web的互操作性测试。
状态
这个模块是一个测试版:我们在生产中依靠它,但我们可能会在收集早期采用者的反馈时做一些改变。我们计划在10月发布稳定版,即Go 1.19发布后不久。
支持和版本划分
connect-go 支持:
在这些参数范围内,Connect遵循语义上的版本划分。