当前位置: 首页 > news >正文

用go写一个微服务gPRC为主RESTful为辅

环境准备

  • Windows 10 + Go 1.24
  • 需要安装的 Go 工具:
    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
    go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
    go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest
    go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
    
  • 还需要 protoc 编译器。可从 https://github.com/protocolbuffers/protobuf/releases 下载预编译二进制(protoc-<version>-win64.zip),解压后将 bin 目录加入系统 PATH。

项目结构

my-microservice/
├── proto/
│   └── user/
│       └── user.proto
├── server/                # gRPC 服务端实现
│   └── main.go
├── gateway/               # gRPC-Gateway HTTP 服务
│   └── main.go
├── gen/                   # 生成的代码(可忽略,由脚本生成)
│   └── proto/
│       └── user/
│           ├── user.pb.go
│           ├── user_grpc.pb.go
│           └── user.pb.gw.go
├── go.mod
└── Makefile               # 或 generate.bat 用于生成代码

步骤 1:定义 Protocol Buffers 文件

proto/user/user.proto

syntax = "proto3";package user;option go_package = "my-microservice/gen/proto/user";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: "user"};}
}message GetUserRequest {string id = 1;
}message CreateUserRequest {User user = 1;
}message User {string id = 1;string name = 2;string email = 3;
}

注意:为了生成 gRPC-Gateway 代码,我们需要导入 google/api/annotations.proto。该文件需要从 googleapis 下载到本地或通过 -I 指定包含路径。我们将 google/api 目录放在项目根目录的 third_party/googleapis 下。


步骤 2:生成 Go 代码

编写一个脚本 generate.bat(Windows 批处理):

@echo off
set PROTOC=protoc
set PROTO_PATH=proto;third_party\googleapis
set OUT_DIR=gen\protoREM 清理旧生成文件
if exist %OUT_DIR% rmdir /s /q %OUT_DIR%
mkdir %OUT_DIR%REM 生成 user.pb.go 和 user_grpc.pb.go
%PROTOC% -I=%PROTO_PATH% --go_out=%OUT_DIR% --go_opt=paths=source_relative --go-grpc_out=%OUT_DIR% --go-grpc_opt=paths=source_relative proto/user/user.protoREM 生成 user.pb.gw.go (gRPC-Gateway)
%PROTOC% -I=%PROTO_PATH% --grpc-gateway_out=%OUT_DIR% --grpc-gateway_opt=paths=source_relative proto/user/user.protoecho Generation complete.

执行该脚本后,将在 gen/proto/user/ 下得到三个文件:

  • user.pb.go (消息定义)
  • user_grpc.pb.go (gRPC 客户端/服务端接口)
  • user.pb.gw.go (gRPC-Gateway 反向代理)

步骤 3:实现 gRPC 服务端

server/main.go

package mainimport ("context""log""net""my-microservice/gen/proto/user""google.golang.org/grpc"
)type userService struct {user.UnimplementedUserServiceServer// 模拟数据库users map[string]*user.User
}func (s *userService) GetUser(ctx context.Context, req *user.GetUserRequest) (*user.User, error) {u, ok := s.users[req.Id]if !ok {return nil, nil // 实际应返回 NotFound 错误}return u, nil
}func (s *userService) CreateUser(ctx context.Context, req *user.CreateUserRequest) (*user.User, error) {u := req.Userif u.Id == "" {// 生成简单 IDu.Id = "123" // 生产环境应使用 UUID}s.users[u.Id] = ureturn u, nil
}func main() {lis, err := net.Listen("tcp", ":50051")if err != nil {log.Fatalf("failed to listen: %v", err)}s := grpc.NewServer()user.RegisterUserServiceServer(s, &userService{users: make(map[string]*user.User),})log.Println("gRPC server listening on :50051")if err := s.Serve(lis); err != nil {log.Fatalf("failed to serve: %v", err)}
}

步骤 4:实现 gRPC-Gateway HTTP 服务

gateway/main.go

package mainimport ("context""log""net/http""my-microservice/gen/proto/user""github.com/grpc-ecosystem/grpc-gateway/v2/runtime""google.golang.org/grpc""google.golang.org/grpc/credentials/insecure"
)func main() {// 连接到 gRPC 服务端conn, err := grpc.DialContext(context.Background(),"localhost:50051",grpc.WithTransportCredentials(insecure.NewCredentials()),grpc.WithBlock(),)if err != nil {log.Fatalf("failed to dial gRPC server: %v", err)}defer conn.Close()// 创建 gRPC-Gateway 多路复用器gwmux := runtime.NewServeMux()// 注册 UserService 的 HTTP 代理if err := user.RegisterUserServiceHandler(context.Background(), gwmux, conn); err != nil {log.Fatalf("failed to register gateway: %v", err)}// 启动 HTTP 服务器addr := ":8080"log.Printf("HTTP server listening on %s", addr)if err := http.ListenAndServe(addr, gwmux); err != nil {log.Fatalf("failed to serve HTTP: %v", err)}
}

步骤 5:创建 go.mod 并整理依赖

在项目根目录执行:

go mod init my-microservice
go get google.golang.org/grpc
go get google.golang.org/protobuf
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get github.com/grpc-ecosystem/grpc-gateway/v2/runtime

运行 go mod tidy 下载所有依赖。


步骤 6:运行与测试

  1. 启动 gRPC 服务端

    go run server/main.go
    

    输出:gRPC server listening on :50051

  2. 启动 HTTP 网关

    go run gateway/main.go
    

    输出:HTTP server listening on :8080

  3. 测试 RESTful API

    创建用户(POST):

    curl -X POST http://localhost:8080/v1/users \-H "Content-Type: application/json" \-d '{"id": "1001", "name": "Alice", "email": "alice@example.com"}'
    

    获取用户(GET):

    curl http://localhost:8080/v1/users/1001
    

    将收到 JSON 响应,例如:

    {"id":"1001","name":"Alice","email":"alice@example.com"}
    
  4. 测试 gRPC 调用(可选)
    可以使用 grpcurl 工具:

    grpcurl -plaintext -d '{"id":"1001"}' localhost:50051 user.UserService/GetUser
    

原理说明

  1. gRPC 作为主通信协议

    • gRPC 基于 HTTP/2,使用 Protocol Buffers 序列化,支持多路复用、双向流,性能高且接口契约强。
    • 服务端实现业务逻辑,通过 protoc 生成的接口确保类型安全。
  2. gRPC-Gateway 辅助提供 RESTful API

    • 在 proto 文件中使用 google.api.http 注解定义了 HTTP 方法与路径到 gRPC 方法的映射。
    • protoc-gen-grpc-gateway 根据注解生成一个反向代理服务器,它接收 HTTP/JSON 请求,将其转换为 gRPC 调用,然后将响应转换回 JSON。
    • 网关无需重写业务逻辑,只需与 gRPC 服务端建立连接,即可将 RESTful 流量无缝转发。
  3. 架构优势

    • 单一契约:只需维护 .proto 文件,即可同时生成 gRPC 和 HTTP 接口,避免 API 定义不一致。
    • 渐进式改造:对外暴露 RESTful 接口便于浏览器、移动端和第三方集成,内部服务间仍使用高效的 gRPC。
    • 生态丰富:可配合 OpenAPI (Swagger) 生成文档、客户端 SDK 等。

注意事项

  • 生产环境中 gRPC 服务端与网关通常部署在不同端口(或同一端口但需特殊处理),本例分开启动便于演示。
  • 示例中未处理错误与认证,实际应添加 TLS、拦截器、日志等。
  • 若要在 Windows 下长期运行,可考虑将两个服务注册为 Windows 服务或使用进程管理器。

通过以上步骤,我们成功构建了一个以 gRPC 为核心、同时提供 RESTful 接口的 Go 微服务。完整代码可打包为项目,按需扩展。

http://www.jsqmd.com/news/439459/

相关文章:

  • Flutter 三方库 posix 的鸿蒙化适配指南 - 掌控底层系统调用、文件权限管理实战、鸿蒙级系统级工具专家
  • 2026年3月喷丝板清洗机厂家推荐,专业制造与品牌保障口碑之选 - 品牌鉴赏师
  • 北京工装设计师推荐:易楷东设计师 - 余小铁
  • 自动化立体仓库核心品牌深度评测:技术与场景适配性解析 - 品牌种草官
  • 2026年3月饭店厨房设备厂家最新推荐,实用省心性价比高 - 品牌鉴赏师
  • 2026年成都酒柜定制厂家推荐:聚焦环保健康与本地化服务的实力之选 - 深度智识库
  • 2026市面上新型撤离舱品牌哪家强?这份排行别错过,撤离舱厂家口碑排行榜优选实力品牌 - 品牌推荐师
  • 2026低空安全防护之选 五家反无人机企业助力空域守护 - 深度智识库
  • 【盘点汇总】哪个厂家的移动转运料仓/中转料仓/周转料仓质量好? - 品牌推荐大师
  • 2026年3月通过式超声波清洗机厂家推荐,专业制造与品牌保障口碑之选 - 品牌鉴赏师
  • 热机械分析仪哪家好?从温度精度到载荷系统,这篇全讲透了! - 品牌推荐大师1
  • 2026年3月东莞独立站公司推荐榜:甄选企业实测解析 - 品牌鉴赏师
  • OpenClaw 的实现逻辑与本质;流式传输形态;
  • Dante记录
  • PbootCMS提示错误信息“未检测到您服务器环境的sqlite3数据库扩展…”
  • 实用指南:04 - SVM核心数据结构详解
  • 2026年成都榻榻米定制厂家哪家好?本地优选指南 - 深度智识库
  • 6.ethercat主站芯片
  • 2026送礼首选!5款真实睡眠仪排名,双龙脉小黑钥直击熬夜加班痛点 - 速递信息
  • PBootCMS上一篇下一篇调用 如何把“没有了”改成英文
  • 路由器--SMP(软件制作平台)语言基础知识之七十七
  • 2026年成都全屋定制“避坑”指南:本地实力工厂榜单与环保选材 - 深度智识库
  • 学生党们最爱用的华为耳机是哪款?音质/降噪/运动/防丢直接封神!
  • 2026 年 3 月企业必看:上海智推时代 GEO 官方对接方式全整理 - 速递信息
  • 灌流器行业头部企业与核心供应链盘点 - 品牌2026
  • 2026年新春第一篇文章
  • 2026年3月留学生求职机构推荐:聚焦企业综合实力与核心竞争力 - 品牌鉴赏师
  • 血液灌流器在肾病治疗中的应用及生产企业推荐 - 品牌2026
  • 话费卡使用攻略:回收平台推荐 - 团团收购物卡回收
  • 2026年除铁设备厂家推荐:胜宇机电全自动粉料除铁器/抽屉式除铁器/电磁浆料除铁机/管道除铁机,适配陶瓷/新能源/化工多行业除铁需求 - 品牌推荐官