Golang实现GRPC与REST微服务开发指南
Golang实现GRPC与REST微服务开发指南 我确实看到了这篇帖子,内容有些相似,但我希望进行更广泛的讨论,并且我的问题略有不同。
因此,我希望建立一些基础架构,我的服务将主要使用 Go/gRPC,在需要时使用 REST,其他情况下则使用 gRPC。
最初的需求比较基础:gRPC、HTTP 包装器、Swagger/OpenAPI(或一些自动文档)。我也在考虑使用 Envoy,但对于使用代理进行服务注册和其他有趣的事情,我还是个新手。
我基本上已经拼凑出了一些能实现这些功能的代码,但老实说,我更愿意不重复造轮子。我真的很惊讶,周围竟然没有其他现成的解决方案,或者也许我只是错过了。
我查看过的东西:
go-kit:
- 优点:它似乎在为扩展、日志记录和服务注册等方面做长远考虑,这都很好。
- 缺点:在我看来,这真的过于复杂了。他们的简单 hello world 示例长达 12 页,只是为了帮我做一个非常简单的入门示例。
go-micro:
- 优点:比 go-kit 简单。
- 缺点:
- 似乎需要特定的生态系统才能工作。
- 添加一个非 Go 语言编写的服务似乎…
Lile:
当我看到这个时,我非常兴奋,但我无法让它运行起来,所以不确定是它本身有问题,还是只是我的问题。
Clayr:
另一个对我来说似乎不工作的项目。根据我的尝试,示例和代码生成似乎相当混乱。
我很希望在 Go 中看到类似 https://www.dropwizard.io/ 的东西,它是一个简单的技术栈,你可以反复使用,让你创建一个服务,并拥有日志记录、健康检查等钩子,但不需要每次你想用一个新响应返回一个新端点时都更新 7 个类。
在我的研究中,我是否遗漏了什么?是每个人都在编写自己的家庭技术栈,还是我正在尝试做的事情并不主流?
更多关于Golang实现GRPC与REST微服务开发指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang实现GRPC与REST微服务开发指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中构建同时支持gRPC和REST的微服务,确实有几个成熟的方案。以下是具体的实现示例:
方案一:gRPC-Gateway(官方推荐)
这是最标准的解决方案,通过protobuf注解自动生成REST代理。
1. 定义proto文件:
syntax = "proto3";
package example;
option go_package = "github.com/example/proto";
import "google/api/annotations.proto";
service UserService {
rpc GetUser(GetUserRequest) returns (User) {
option (google.api.http) = {
get: "/v1/users/{id}"
};
}
rpc CreateUser(CreateUserRequest) returns (User) {
option (google.api.http) = {
post: "/v1/users"
body: "*"
};
}
}
message GetUserRequest {
string id = 1;
}
message CreateUserRequest {
string name = 1;
string email = 2;
}
message User {
string id = 1;
string name = 2;
string email = 3;
}
2. 生成代码:
# 安装工具
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
# 生成代码
protoc -I . \
--go_out=./gen \
--go-grpc_out=./gen \
--grpc-gateway_out=./gen \
--openapiv2_out=./docs \
user.proto
3. 服务实现:
package main
import (
"context"
"log"
"net"
"net/http"
"github.com/example/proto/gen"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
)
type server struct {
gen.UnimplementedUserServiceServer
}
func (s *server) GetUser(ctx context.Context, req *gen.GetUserRequest) (*gen.User, error) {
return &gen.User{
Id: req.Id,
Name: "John Doe",
Email: "john@example.com",
}, nil
}
func (s *server) CreateUser(ctx context.Context, req *gen.CreateUserRequest) (*gen.User, error) {
return &gen.User{
Id: "123",
Name: req.Name,
Email: req.Email,
}, nil
}
func main() {
// 启动gRPC服务
lis, _ := net.Listen("tcp", ":50051")
grpcServer := grpc.NewServer()
gen.RegisterUserServiceServer(grpcServer, &server{})
go grpcServer.Serve(lis)
// 启动REST网关
ctx := context.Background()
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithInsecure()}
err := gen.RegisterUserServiceHandlerFromEndpoint(ctx, mux, "localhost:50051", opts)
if err != nil {
log.Fatal(err)
}
// 提供OpenAPI文档
fs := http.FileServer(http.Dir("./docs"))
http.Handle("/docs/", http.StripPrefix("/docs/", fs))
http.Handle("/", mux)
log.Println("REST server listening on :8080")
http.ListenAndServe(":8080", nil)
}
方案二:Connect(现代替代方案)
Connect提供更简单的API,同时支持gRPC、gRPC-Web和REST。
1. 安装:
go install github.com/bufbuild/buf/cmd/buf@latest
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
go install github.com/bufbuild/connect-go/cmd/protoc-gen-connect-go@latest
2. 服务实现:
package main
import (
"context"
"log"
"net/http"
"github.com/bufbuild/connect-go"
"github.com/example/proto/gen/user/v1/userv1connect"
userv1 "github.com/example/proto/gen/user/v1"
)
type UserServer struct{}
func (s *UserServer) GetUser(
ctx context.Context,
req *connect.Request[userv1.GetUserRequest],
) (*connect.Response[userv1.User], error) {
user := &userv1.User{
Id: req.Msg.Id,
Name: "John Doe",
Email: "john@example.com",
}
return connect.NewResponse(user), nil
}
func main() {
userServer := &UserServer{}
mux := http.NewServeMux()
path, handler := userv1connect.NewUserServiceHandler(userServer)
mux.Handle(path, handler)
// 自动支持RESTful端点
log.Println("Listening on :8080")
http.ListenAndServe(":8080", mux)
}
方案三:自定义包装器(轻量级)
如果只需要基础功能,可以自己实现:
package main
import (
"encoding/json"
"net/http"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type RESTHandler struct {
grpcClient YourServiceClient
}
func NewRESTHandler() *RESTHandler {
conn, _ := grpc.Dial("localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()))
return &RESTHandler{
grpcClient: NewYourServiceClient(conn),
}
}
func (h *RESTHandler) GetUser(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
// 调用gRPC
resp, err := h.grpcClient.GetUser(r.Context(), &GetUserRequest{Id: id})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(resp)
}
func main() {
handler := NewRESTHandler()
http.HandleFunc("/users", handler.GetUser)
http.ListenAndServe(":8080", nil)
}
健康检查和指标
集成prometheus指标和健康检查:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
)
func setupMonitoring() {
// Prometheus指标
http.Handle("/metrics", promhttp.Handler())
// 健康检查
healthServer := health.NewServer()
healthServer.SetServingStatus("", grpc_health_v1.HealthCheckResponse_SERVING)
// 就绪检查端点
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
}
这些方案都提供了生产就绪的gRPC+REST实现。gRPC-Gateway是最完整的解决方案,Connect提供了更现代的API,自定义包装器则适合简单场景。

