基于 Dubbo 定义的 Triple 协议,你可以轻松编写浏览器、gRPC 兼容的 RPC 服务,并让这些服务同时运行在 HTTP/1 和 HTTP/2 上。Dubbo Node.js SDK 支持使用 IDL 或编程语言特有的方式定义服务,并提供一套轻量的 API 来发布或调用这些服务。
本示例演示了基于 Triple 协议的 RPC 通信模式,示例使用 Protocol Buffer 定义 RPC 服务,并演示了代码生成、服务发布和服务访问等过程。
因为使用 Protocol Buffer 的原因,我们首先需要安装相关的代码生成工具,这包括 @bufbuild/protoc-gen-es
、@bufbuild/protobuf
、@apachedubbo/protoc-gen-apache-dubbo-es
、@apachedubbo/dubbo
。
npm install @bufbuild/protoc-gen-es @bufbuild/protobuf @apachedubbo/protoc-gen-apache-dubbo-es @apachedubbo/dubbo
现在,使用 Protocol Buffer (IDL) 来定义一个 Dubbo 服务。
创建目录,并生成文件
mkdir -p proto && touch proto/example.proto
写入内容
syntax = "proto3";
package apache.dubbo.demo.example.v1;
message SayRequest {
string sentence = 1;
}
message SayResponse {
string sentence = 1;
}
service ExampleService {
rpc Say(SayRequest) returns (SayResponse) {}
}
这个文件声明了一个叫做 ExampleService
的服务,为这个服务定义了 Say
方法以及它的请求参数 SayRequest
和返回值 SayResponse
。
创建 gen 目录,做为生成文件放置的目标目录
mkdir -p gen
运行以下命令,在 gen 目录下生成代码文件
PATH=$PATH:$(pwd)/node_modules/.bin \
protoc -I proto \
--es_out gen \
--es_opt target=ts \
--apache-dubbo-es_out gen \
--apache-dubbo-es_opt target=ts \
example.proto
运行命令后,应该可以在目标目录中看到以下生成的文件:
├── gen
│ ├── example_dubbo.ts
│ └── example_pb.ts
├── proto
│ └── example.proto
接下来我们就需要添加业务逻辑了,实现 ExampleService ,并将其注册到 DubboRouter 中。
创建 dubbo.ts 文件
import type { DubboRouter } from "@apachedubbo/dubbo";
import { ExampleService } from "./gen/example_dubbo";
export default (router: DubboRouter) =>
// registers apache.dubbo.demo.example.v1
router.service(ExampleService, {
// implements rpc Say
async say(req) {
return {
sentence: `You said: ${req.sentence}`,
};
},
}, { serviceGroup: 'dubbo', serviceVersion: '1.0.0' });
Dubbo 服务可以嵌入到普通的 Node.js 服务器、Next.js、Express 或 Fastify 中。 在这里我们将使用 Fastify,所以让我们安装 Fastify 以及我们为 Fastify 准备的插件。
npm install fastify @apachedubbo/dubbo-fastify
创建 server.ts 文件,新建一个 Server,把上一步中实现的 ExampleService
注册给它。
接下来就可以直接初始化和启动 Server 了,它将在指定的端口接收请求。
import { fastify } from "fastify";
import { fastifyDubboPlugin } from "@apachedubbo/dubbo-fastify";
import routes from "./dubbo";
async function main() {
const server = fastify();
await server.register(fastifyDubboPlugin, {
routes,
});
server.get("/", (_, reply) => {
reply.type("text/plain");
reply.send("Hello World!");
});
await server.listen({ host: "localhost", port: 8080 });
console.log("server is listening at", server.addresses());
}
void main();
最后,运行代码启动服务
npx tsx server.ts
最简单方式是使用 HTTP/1.1 POST 请求访问服务,参数则作以标准 JSON 格式作为 HTTP 负载传递。如下是使用 cURL 命令的访问示例:
curl \
--header 'Content-Type: application/json' \
--header 'TRI-Service-Version: 1.0.0' \
--header 'TRI-Service-group: dubbo' \
--data '{"sentence": "Hello World"}' \
http://localhost:8080/apache.dubbo.demo.example.v1.ExampleService/Say
也可以使用标准的 Dubbo client 请求服务,我们首先需要从生成代码即 dubbo-node 包中获取服务代理,为它指定 server 地址并初始化,之后就可以发起起 RPC 调用了。
创建 client.ts 文件。
import { createPromiseClient } from "@apachedubbo/dubbo";
import { ExampleService } from "./gen/example_dubbo";
import { createDubboTransport } from "@apachedubbo/dubbo-node";
const transport = createDubboTransport({
baseUrl: "http://localhost:8080",
httpVersion: "1.1",
});
async function main() {
const client = createPromiseClient(ExampleService, transport, { serviceVersion: '1.0.0', serviceGroup: 'dubbo' });
const res = await client.say({ sentence: "Hello World" });
console.log(res);
}
void main();
运行客户端
npx tsx client.ts
参考开发运行在浏览器上的 web 应用,了解如何开发能访问 Dubbo 后端服务的浏览器页面。