IDEA搭建跨语言混合微服务架构完整文档(Go网关+SpringBoot gRPC+统一Proto)
一、文档说明
1.1 适用环境
-
操作系统:Windows
-
开发工具:IDEA 2024
-
Go 版本:1.21+
-
JDK 版本:17
-
SpringBoot 版本:3.2.x
-
Protoc 版本:v26+
1.2 架构简介
本项目采用跨语言混合微服务架构,结合 SpringBoot 业务开发效率与 Go 网关高性能转发能力:
-
SpringBoot:实现核心业务,对内提供标准 gRPC 二进制服务,不暴露 HTTP 接口
-
Go grpc-gateway:统一对外 HTTP 网关,自动完成 HTTP/JSON ↔ gRPC 协议转换
-
go-proto 公共模块:统一维护 Protobuf 定义,一键生成 Go、Java 双端代码,彻底解决跨语言接口不一致问题
1.3 调用链路
前端HTTP请求 → Go Gateway 路由匹配 → 自动转 gRPC 请求 → 内网调用 SpringBoot gRPC服务 → 原路返回 JSON 数据
1.4 项目整体结构
grpc-mix-demo/
├─ go-proto/ # 公共Proto模块(核心)
│ ├─ api/google/api/ # 网关HTTP注解proto
│ ├─ api/user/user.proto # 跨语言统一业务接口
│ ├─ gen/ # Go生成代码
│ ├─ java-gen/ # Java生成代码
│ ├─ gen.bat # 一键批量生成脚本
│ └─ go.mod
├─ api-gateway/ # Go grpc-gateway网关服务
│ ├─ cmd/gateway/main.go
│ └─ go.mod
└─ spring-user/ # SpringBoot gRPC业务服务
├─ src/main/proto/
├─ src/main/java/
└─ pom.xml
二、前置环境配置
2.1 Go环境配置
配置国内代理,加速依赖下载:
go env -w GOPROXY=https://goproxy.cn,direct
安装 protoc 编译插件:
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/protoc-gen-grpc-java@latest
2.2 IDEA必备插件
-
Go(官方)
-
Protocol Buffers
-
Spring Initializr
三、模块一:公共 Proto 模块 go-proto
3.1 创建模块
IDEA 新建 Empty Project,手动创建 Go Module 模块 go-proto,执行目录初始化:
mkdir -p api/google/api api/user gen java-gen
go get google.golang.org/grpc
go get google.golang.org/protobuf
go get github.com/grpc-ecosystem/grpc-gateway/v2
3.2 手动创建网关依赖注解文件(解决新版网关缺失问题)
新版 grpc-gateway v2 已无 runtime/googleapis,手动创建以下两个文件。
文件1:api/google/api/http.proto
syntax = "proto3";
package google.api;
// Go代码生成路径,本地项目统一改成 ./gen/google/api;googleapi
option go_package = "./gen/google/api;googleapi";
// 单个RPC方法的HTTP映射规则
message HttpRule {
// 必填:匹配当前RPC方法名(全限定名,protoc自动填充,无需手动写)
string selector = 1;
// 标准HTTP方法路径(六选一,一个规则只能写一种)
string get = 2;
string put = 3;
string post = 4;
string delete = 5;
string patch = 6;
// 自定义HTTP方法(如OPTIONS、HEAD),搭配CustomHttpPattern使用
CustomHttpPattern custom = 8;
// 请求体映射规则
// body = "*":所有POST/PUT参数全部从JSON body读取
// body = "field":只把请求结构体里的field字段放到body,其余走URL路径参数
string body = 7;
// 多条绑定规则:一个RPC可以绑定多个HTTP接口(GET路径 + POST提交)
repeated HttpRule additional_bindings = 11;
}
// 自定义非标准HTTP方法(HEAD/OPTIONS等)
message CustomHttpPattern {
string kind = 1; // HTTP方法名,如 "HEAD"
string path = 2; // 接口路径
}
文件2:api/google/api/annotations.proto
syntax = "proto3";
package google.api;
option go_package = "../../gen/google/api;googleapi";
// 导入HttpRule定义
import "google/api/http.proto";
// 导入protobuf原生描述符,用于扩展MethodOptions
import "google/protobuf/descriptor.proto";
// 扩展protobuf原生的方法选项:给每个rpc方法新增http选项
extend google.protobuf.MethodOptions {
// 固定扩展ID 72295728,官方预留ID不可修改
HttpRule http = 72295728;
}
3.3 业务统一 Proto 文件(跨Go/Java共用)
路径:api/user/user.proto
syntax = "proto3";
package user;
// 生成代码输出到 gen/user,包名 userpb
option go_package = "/gen/user;userpb";
// 导入网关HTTP注解
import "google/api/annotations.proto";
// 请求参数
message GetUserReq {
int64 uid = 1;
}
// 响应参数
message GetUserResp {
int64 uid = 1;
string username = 2;
int32 age = 3;
}
// 用户GRPC服务
service UserService {
rpc GetUser(GetUserReq) returns (GetUserResp) {
// 绑定RESTful HTTP接口
option (google.api.http) = {
get: "/api/v1/user/{uid}"
additional_bindings {
post: "/api/v1/user/get"
body: "*"
}
};
}
}
3.4 一键批量生成脚本 gen.bat
自动清理旧代码、递归扫描全部proto、同时生成 Go + Java 双端代码:
@echo off
:: 切换控制台编码为UTF-8,解决乱码
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 脚本所在根目录
set "ROOT=%~dp0"
protoc ^
--proto_path=%ROOT%api ^
--go_out=%ROOT% ^
--go-grpc_out=%ROOT% ^
--grpc-gateway_out=%ROOT% ^
%ROOT%api\user\user.proto ^
%ROOT%api\google\api\http.proto ^
%ROOT%api\google\api\annotations.proto
if %errorlevel% equ 0 (
echo 【成功】proto文件编译完成!
) else (
echo 【失败】protoc编译出错,检查proto语法、插件环境!
)
pause
3.5 IDEA 修复 proto 标红
File → Settings → Languages & Frameworks → Protocol Buffers 添加导入路径:$PROJECT_ROOT$/go-proto/api,重启IDEA生效。
四、模块二:SpringBoot 微服务 spring-user
4.1 项目创建
基于 Spring Initializr 创建,JDK17,依赖:grpc-spring-boot-starter、Lombok
4.2 pom.xml 核心配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
<grpc.version>1.64.0</grpc.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<version>2.15.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.25.3:exe:${osdetector.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${osdetector.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
4.3 配置文件 application.yml
grpc:
erver:
port:9090
spring:
application:
name: spring-user-service
4.4 gRPC 业务实现类
package com.example.springuser.service;
import com.example.springuser.grpc.GetUserReq;
import com.example.springuser.grpc.GetUserResp;
import com.example.springuser.grpc.UserServiceGrpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
public class UserGrpcServiceImpl extends UserServiceGrpc.UserServiceImplBase {
@Override
public void getUser(GetUserReq request, StreamObserver<GetUserResp> responseObserver) {
long uid = request.getUid();
GetUserResp resp = GetUserResp.newBuilder()
.setUid(uid)
.setUsername("业务用户_" + uid)
.setAge(26)
.build();
responseObserver.onNext(resp);
responseObserver.onCompleted();
}
}
4.5 启动类
package com.example.springuser;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringUserApplication {
public static void main(String[] args) {
SpringApplication.run(SpringUserApplication.class, args);
}
}
五、模块三:Go 网关 api-gateway
5.1 模块创建与依赖配置
新建 Go Module 模块 api-gateway,修改 go.mod:
module api-gateway
go 1.22
replace go-proto => ../go-proto
require go-proto v0.0.0-00010101000000-000000000000
require (
github.com/grpc-ecogrpc-gateway/v2 v2.20.0
google.golang.org/grpc v1.64.0
)system/
5.2 网关主程序 main.go
package main
import (
"context"
"log"
"net/http"
"go-proto/gen/user"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
.golang.org/grpc/credentials/insecure"
)
const (
springGRPCAd27.0.0.1:9090"
httpListenAddr = ":8080"
)
func main() {
.Background()
ctx, cancel := context.WithCancel(ctx)
defconn, err := grpc.DialContext(
ctx,
springGR grpc.WithTransportCredentials(insecure.NewCredentials()), nil {
log.Fatalf("连接Spring gRPC服务失败 defer conn.Close()
mux := runtime.NewServeMux()
err = userpb.RegisterU, mux, conn)
if err != nil {
lv", err)
}
log.Printf("网关启动成功,监听端口 %s", h
_ = http.ListenAndServe(httpListenAddr, mux)
}ttpListenAddr)og.Fatalf("注册网关路由失败:%serServiceHandler(ctx:%v", err)
}
)
if err !=PCAddr,
grpc.WithBlock(),
er cancel()
ctx := contextdr = "1 "google
六、项目启动与测试
6.1 严格启动顺序
-
启动 spring-user(先启动gRPC业务服务)
-
启动 api-gateway(再启动网关)
6.2 接口测试
GET 请求
http://127.0.0.1:8080/api/v1/user/1001
POST 请求
地址:http://127.0.0.1:8080/api/v1/user/get Body:{"uid":2002}
七、常见报错与解决方案
7.1 google/api/annotations.proto 找不到
新版网关无内置 googleapis,手动创建 api/google/api 下两个注解文件即可。
7.2 Output filenames must never have a relative path
禁止 go_package 使用 ../../,改为模块内路径 ./gen/user;userpb。
7.3 找不到 google.golang.org/genproto
修改 google 注解 proto 的 go_package,生成本地代码,不依赖远程官方包。
7.4 网关连接超时
确保 Spring 服务9090端口正常启动、使用明文连接、关闭防火墙拦截。
7.5 修改proto后接口404
重新执行 gen.bat 生成代码,重启网关。
八、生产优化方案
-
接入 Nacos/Etcd 实现服务发现与负载均衡,替换硬编码地址
-
网关增加跨域、鉴权、限流、统一返回体、链路追踪中间件
-
Docker 容器化部署,内网只暴露 gRPC 端口,公网仅开放网关
-
自动生成 OpenAPI 接口文档
九、总结
本文基于IDEA完整搭建Go网关 + SpringBoot gRPC业务 + 统一Proto混合微服务架构,解决了新版protoc、grpc-gateway所有兼容性报错,实现一套Proto跨双语言统一接口、HTTP自动转gRPC协议、内网业务隔离、外网流量统一收敛的企业级微服务架构,可直接用于学习、开发与项目落地。
更多推荐





所有评论(0)