如何在同一端口同时运行Express服务器与gRPC服务器?
解决方案:让Express与gRPC共享同一端口
在Google Cloud Run单容器环境下,你可以通过复用同一个HTTP服务器实例的方式让Express和gRPC共享端口,核心思路是利用gRPC基于HTTP/2的特性,让Node.js的HTTP服务器同时处理普通HTTP请求(Express)和gRPC请求。
实现步骤
1. 安装依赖
确保安装必要的包:
npm install express @grpc/grpc-js @grpc/proto-loader
2. 编写代码
先创建一个gRPC proto定义文件(比如helloworld.proto):
syntax = "proto3"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }
然后修改你的Express应用代码,整合gRPC服务:
const express = require('express'); const http = require('http'); const grpc = require('@grpc/grpc-js'); const protoLoader = require('@grpc/proto-loader'); const app = express(); const port = process.env.PORT || 8080; // --- Express 业务逻辑 --- app.use(express.json()); app.get('/', (req, res) => { res.send('Hello from Express!'); }); // 创建共享的HTTP服务器实例 const httpServer = http.createServer(app); // --- gRPC 服务配置 --- // 加载proto文件 const packageDefinition = protoLoader.loadSync( './helloworld.proto', { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true } ); const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld; // 实现gRPC服务方法 function sayHello(call, callback) { callback(null, { message: `Hello gRPC, ${call.request.name}!` }); } // 创建gRPC服务器并复用Express的HTTP服务器 const grpcServer = new grpc.Server({ httpServer: httpServer // 关键:让gRPC共享已有的HTTP服务器端口 }); // 注册gRPC服务 grpcServer.addService(helloProto.Greeter.service, { SayHello: sayHello }); // --- 启动服务 --- grpcServer.start(); httpServer.listen(port, () => { console.log(`Service running on port ${port} in ${app.get("env")} mode`); console.log('gRPC server ready on the same port'); });
原理说明
- gRPC本质上是基于HTTP/2的协议,Node.js的HTTP服务器可以同时处理HTTP/1.1(Express默认)和HTTP/2请求。
- 通过将gRPC服务器绑定到Express使用的同一个HTTP实例,服务器会自动根据请求的特征(比如
Content-Type: application/grpc)区分处理:普通HTTP请求由Express路由,gRPC请求由gRPC服务器处理。 - Google Cloud Run支持HTTP/2,且会自动完成外部请求的HTLS终止,因此你无需在代码中配置证书,直接使用HTTP服务器即可。
测试验证
- 测试Express:用浏览器或curl访问
http://localhost:8080,会返回Express的响应。 - 测试gRPC:使用
grpcurl工具(需提前安装)执行:
会收到gRPC服务的响应。grpcurl -plaintext -d '{"name": "test"}' localhost:8080 helloworld.Greeter/SayHello
内容的提问来源于stack exchange,提问作者ololo
相关产品推荐
相关产品推荐

