Based on the Triple protocol defined by Dubbo, you can easily write browser and gRPC compatible RPC services that run simultaneously on HTTP/1 and HTTP/2. The Dubbo Node.js SDK supports defining services using IDL or language-specific methods and provides a lightweight API for publishing or invoking these services.
This example demonstrates the RPC communication model based on the Triple protocol, using Protocol Buffers to define RPC services, and illustrating processes such as code generation, service publishing, and service access.
Due to the use of Protocol Buffers, we first need to install the relevant code generation tools, including @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
Now, use Protocol Buffers (IDL) to define a Dubbo service.
Create a directory and generate a file.
mkdir -p proto && touch proto/example.proto
Write the content.
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) {}
}
This file declares a service called ExampleService
, defining a Say
method along with its request parameter SayRequest
and return value SayResponse
.
Create a gen directory as the target directory for generated files.
mkdir -p gen
Run the following command to generate code files in the gen directory.
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
After running the command, you should see the following generated files in the target directory:
├── gen
│ ├── example_dubbo.ts
│ └── example_pb.ts
├── proto
│ └── example.proto
Next, we’ll need to add business logic to implement ExampleService and register it with DubboRouter.
Create a dubbo.ts file.
import { 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 services can be embedded into a regular Node.js server, Next.js, Express, or Fastify. Here we will use Fastify, so let’s install Fastify and the plugin we prepared for Fastify.
npm install fastify @apachedubbo/dubbo-fastify
Create a server.ts file, create a Server, and register the implemented ExampleService
from the previous step. Then initialize and start the Server, which will receive requests on the specified port.
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();
Finally, run the code to start the service.
npx tsx server.ts
The simplest way to access the service is to use an HTTP/1.1 POST request, passing parameters in standard JSON format as the HTTP payload. Below is an example using the cURL command:
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
You can also use a standard Dubbo client to request the service. We first need to get the service proxy from the generated code, i.e., the dubbo-node package, specify the server address for it, and initialize it before we can make the RPC call.
Create a client.ts file.
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();
Run the client.
npx tsx client.ts