In Quick Start, you have successfully run the basic example of tRPC-Java, but
that is just the beginning. In this tutorial, you will continue to learn:
- The way to define
tRPC-Javaservices by Protocol Buffer. - The way to configure
tRPC-Javaservices by YAML file. - The way to integrate
tRPC-Javawith Spring Boot. - The extension capabilities that
tRPC-Javahave. - Various features supported by
tRPC-Java.
To achieve cross-language compatibility, tRPC relies on the Protocol Buffer v3 (referred to
as protobuf in the following tutorial) for its services definition. You can refer to
its Official Documents for more information.
tRPC-Java already provides the minimum service dependency. Before starting to customize your
service, you can include the following dependency:
<dependency>
<groupId>com.tencent.trpc</groupId>
<artifactId>trpc-mini</artifactId>
<version>${tRPC-Java.version}</version>
</dependency>The example codes in the
tRPC-Javarepository already include the above dependency, you can skip this section and proceed with the following tutorial if you are going to run the example codes in thetRPC-Javarepository.
To define a new service, you need to declare it in protobuf first. The following example defines a
service named GreeterService:
service GreeterService {
// ...
}In a service, there can be multiple methods defined within the service body. The following example
demonstrates the definition of a method called sayHello for the service GreeterService. This
method takes HelloRequest as its parameter and returns HelloResponse.
service GreeterService {
rpc sayHello (HelloRequest) returns (HelloResponse) {}
}
message HelloRequest {
// ...
}
message HelloResponse {
// ...
}A detailed tRPC services definition in protobuf can be found
at trpc-java-demo/src/main/proto/demo.proto.
Indeed, protobuf provides a language-independent service definition. You can use
the trpc-maven-plugin to translate the protobuf definition file into
stub codes for tRPC-Java.
The core components of the translated codes are some service interfaces annotated
with @TRpcService and @TRpcMethod, as shown below:
// TRpcService is used to define the service name, the format of the tRPC service is a dot-seperated string start with trpc.
@TRpcService(name = "trpc.TestApp.TestServer.GreeterService")
public interface GreeterserviceAPI {
// TRpcMethod is used to define method name.
@TRpcMethod(name = "sayHello")
HelloRequestProtocol.HelloResponse sayHello(RpcContext context,
HelloRequestProtocol.HelloRequest request);
}A service interface generated by trpc-maven-plugin can be found
at trpc-java-demo/target/generated-sources/trpc/java/com/tencent/trpc/demo/proto/GreeterserviceAPI.java
.
In addition to regular interfaces,
trpc-maven-plugincan also generate asynchronous interfaces. You can choose either one to use based on your requirements.
Implement the generated service interface with your own businesses, as follows:
public class GreeterServiceImpl implements GreeterserviceAPI {
@Override
public HelloRequestProtocol.HelloResponse sayHello(RpcContext context,
HelloRequestProtocol.HelloRequest request) {
// do your business
return something;
}
}An example can be found
at trpc-java-demo/src/main/java/com/tencent/trpc/demo/server/impl/GreeterServiceImpl.java.
The client side only needs generated service interfaces, such as GreeterserviceAPI
and GreeterserviceAsyncAPI, and no need to implement it.
In the Quick Start guide, tRPC-Java demonstrates programmatically configuring
the framework. However, this tutorial will focus on configuring tRPC-Java using a YAML
configuration file.
The following YAML configuration example demonstrates the way to define a tRPC-Java local service
in the server side:
server:
app: TestApp # App name
server: TestServer # Server name
local_ip: 127.0.0.1 # Local ip
service: # Service list
- name: trpc.TestApp.TestServer.Greeter1 # Service name
impls: # Service implement classes
- com.tencent.trpc.demo.server.impl.GreeterServiceImpl
ip: 127.0.0.1 # Listen ip
port: 12321 # Listen port
network: tcp # Network type, tcp or udp
protocol: trpc # Protocol type, default is trpc
serialization: pb # Serialization type, default is pb
transport: netty # Communication transporter, default is nettyAn example can be found at trpc-java-demo/src/main/resources/trpc_java_server.yaml.
The following YAML configuration example demonstrates the way to define a tRPC-Java remote service
in the client side:
server: # Server config, used as caller service info
app: TestApp # App name
server: TestServer # Server name
local_ip: 127.0.0.1 # Local ip
client: # Client configs
service:
- name: trpc.TestApp.TestServer.Greeter1 # Service name
interface: com.tencent.trpc.demo.proto.GreeterserviceAPI # Service interface
naming_url: ip://127.0.0.1:12321 # Router address
network: tcp # Network type, tcp or udp
protocol: trpc # Protocol type, default is trpc
serialization: pb # Serialization type, default is pb
transport: netty # Communication transporter, default is nettyAn example can be found at trpc-java-demo/src/main/resources/trpc_java_client.yaml.
Usually, as a
tRPC-Javaapplication can act as both a server and a client, the above server and client configurations can be combined and defined in the same configuration file.
A more detailed YAML configuration reference can be found at YAML Configurations
After properly configured the server YAML configuration file, you can start the tRPC server with the following codes:
class Server {
public static void main(String[] args) {
TRpcSystemProperties.setProperties(TRpcSystemProperties.CONFIG_PATH, pathToServerYaml);
Main.main(args);
}
}- An example can be found
at
trpc-java-demo/src/main/java/com/tencent/trpc/demo/example/yaml/ServerTest.java. - To run the example codes, you can execute the following command:
$ mvn exec:java -pl :trpc-java-demo -Dexec.cleanupDaemonThreads=false -Dexec.mainClass=com.tencent.trpc.demo.example.yaml.ServerTest
After properly configured the client YAML configuration file, you can start the tRPC client with the following codes:
class Client {
public static void main(String[] args) {
TRpcSystemProperties.setProperties(TRpcSystemProperties.CONFIG_PATH, pathToServerYaml);
Main.main(args);
GreeterserviceAPI proxy = TRpcProxy.getProxy("trpc.TestApp.TestServer.Greeter1",
GreeterserviceAPI.class);
// do some test with proxy
}
}- An example can be found
at
trpc-java-demo/src/main/java/com/tencent/trpc/demo/example/yaml/ClientTest.java. - To run the example codes, you can execute the following command:
$ mvn exec:java -pl :trpc-java-demo -Dexec.cleanupDaemonThreads=false -Dexec.mainClass=com.tencent.trpc.demo.example.yaml.ClientTest
The earlier examples introduced the normal one-request-one-response RPC. tRPC-Java also supports
streaming RPC, HTTP, and more.
Streaming RPC supports more flexible interactions between clients and servers. It can be divided
into the following three modes:
- Client-side streaming: Allows the client to send multiple messages in sequence, and the server returns a message after receiving all of them. It is a many-to-one relationship.
- Server-side streaming: Allows the server to returns multiple messages for one client message. It is a one-to-many relationship.
- Bidirectional streaming: Allows the client and the server to send messages to each other in parallel. It is a many-to-many relationship.
In the stream created during the same request, the receiver receives the messages in the exact order they were sent by the requester.
Unlike normal RPCs, declaring streaming RPCs in protobuf requires the use of the stream keyword,
as follows:
service StreamGreeterService {
rpc clientSayHellos (stream HelloRequest) returns (HelloResponse);
rpc serverSayHellos (HelloRequest) returns (stream HelloResponse);
rpc allSayHellos (stream HelloRequest) returns (stream HelloResponse);
}Note: Currently, it is not supported to declare both normal and streaming RPCs in the same service due to differences in their underlying implementations.
The underlying implementations of the streaming functions in tRPC-Java are depend
on Reactor. The above protobuf definitions may translate to the
following codes:
@TRpcService(name = "trpc.TestApp.TestServer.Greeter")
public interface StreamGreeterService {
@TRpcMethod(name = "serverSayHellos")
Flux<HelloRequestProtocol.HelloResponse> serverSayHellos(RpcContext ctx,
HelloRequestProtocol.HelloRequest request);
@TRpcMethod(name = "clientSayHellos")
Mono<HelloRequestProtocol.HelloResponse> clientSayHellos(RpcContext ctx,
Publisher<HelloRequestProtocol.HelloRequest> requests);
@TRpcMethod(name = "allSayHellos")
Flux<HelloRequestProtocol.HelloResponse> allSayHellos(RpcContext ctx,
Publisher<HelloRequestProtocol.HelloRequest> requests);
}As the specifications of
FluxandMonoimply, you can simply infer the stream mode by the signature of the method.
An example definition can be found at trpc-java-demo/src/main/proto/demo.proto.
The configurations of streaming and normal RPCs are same, an example can be found
at trpc-java-demo/src/main/java/com/tencent/trpc/demo/example/stream.
The way to run example codes is as follows:
- To run server side example:
$ mvn exec:java -pl :trpc-java-demo -Dexec.cleanupDaemonThreads=false -Dexec.mainClass=com.tencent.trpc.demo.example.stream.ServerTest
- To run client side example:
$ mvn exec:java -pl :trpc-java-demo -Dexec.cleanupDaemonThreads=false -Dexec.mainClass=com.tencent.trpc.demo.example.stream.ClientTest
To translate normal RPC to HTTP in tRPC-Java, only the following two configuration items under
the service configuration section need to be reconfigured:
- Change
protocolfromtrpc(default value) tohttp. - Change
transporterfromnetty(default value) tojetty.
An example configuration file can be found
at trpc-java-demo/src/main/resources/trpc_java_server.yaml.
The service named with trpc.TestApp.TestServer.Greeter3 in the above example configuration file is
an HTTP service. The URL address format of a tRPC HTTP service
is /{@TRpcService.name}/{@TRpcMethod.name}, which is the combination of the annotates. The address
of trpc.TestApp.TestServer.Greeter3 in the example file
is http://127.0.0.1:12322/trpc.TestApp.TestServer.GreeterService/sayHello.
The following command can be used to access the above example HTTP service:
$ curl -XPOST -H"Content-Type: application/json" -d'{"message": "tRPC-Java"}' http://127.0.0.1:12322/trpc.TestApp.TestServer.GreeterService/sayHelloIn addition to the basic method to access a HTTP service, tRPC-Java supports to configure a remote
HTTP service as a tRPC client, an example can be found
at trpc-java-demo/src/main/resources/trpc_java_client.yaml.
If you want to change the default URL address, you can add an alias option in the protobuf
definition, as follows:
import "trpc.proto";
service GreeterService2 {
rpc sayHi (HelloRequest) returns (HelloResponse) {
option (trpc.alias) = "/api/hi";
}
}An example definition can be found at trpc-java-demo/src/main/proto/demo.proto.
The aliased service can be accessed with the following URL:
$ curl -XPOST -H"Content-Type: application/json" -d'{"message": "tRPC-Java"}' http://127.0.0.1:12322/api/hitRPC-Java is friendly to Spring Boot and other Spring environments. When using tRPC-JAVA with
Spring Boot, the separated YAML configuration file can be replaced by the application.yml file of
Spring Boot, as shown in example trpc-spring-server-demo/src/main/resources/application.yml.
After properly configuring the application.yml file, all you need to do to run a tRPC-Java
application is to add the @EnableTRpc annotation to the Spring Boot startup class.
@EnableTRpc
@SpringBootApplication
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}An example can be found
at trpc-spring-server-demo/src/main/com/tencent/trpc/spring/demo/server/ServerApplication.java.
If you want to integrate tRPC-Java with SpringMVC, you can add the following dependency in
your pom.xml:
<dependency>
<groupId>com.tencent.trpc</groupId>
<artifactId>trpc-springmvc</artifactId>
<version>${tRPC-Java.version}</version>
</dependency>Then you can add any normal SpringMVC Controllers or tRPC-Java services as mentioned before.
An example can be found
at trpc-spring-server-demo/src/main/com/tencent/trpc/spring/demo/server/controller/.
Since the example codes do not add the Spring Boot plugin, you can run them as follows:
- To run server side example:
$ mvn exec:java -pl :trpc-spring-server-demo -Dexec.cleanupDaemonThreads=false -Dexec.mainClass=com.tencent.trpc.spring.demo.ServerApplication
- To run client side example:
$ mvn exec:java -pl :trpc-spring-client-demo -Dexec.cleanupDaemonThreads=false -Dexec.mainClass=com.tencent.trpc.spring.demo.ClientApplication
The normal Spring Boot application can be packaged as a single jar file, which can be run directly.
tRPC-Java has rich scalability, you can inject various new capabilities into the RPC process
through Filters, and the Plugin mechanism allows you to easily integrate new functions.
Filter
likes an onion. An RPC goes through each layer of the onion in turn. You can customize this onion
model through Filters.
To write a Filter, you need to implement the Filter interface firstly:
public class DemoFilter implements Filter {
@Override
public CompletionStage<Response> filter(Invoker<?> filterChain, Request req) {
try {
System.out.println("enter filter");
return filterChain.invoke(req)
.whenComplete((r, t) -> System.out.println("filter completed"));
} finally {
System.out.println("exit filter");
}
}
}An example can be found at trpc-java-demo/src/main/com/tencent/trpc/demo/filter/DemoFilter.java.
After writing the Filter class, you need to name and register it with
the META-INF/trpc/com.tencent.trpc.core.filter.spi.Filter file as follows:
demoFilter=com.tencent.trpc.demo.filter.DemoFilterAfter registering the Filter, you can use it by referencing its name in the YAML configuration file:
client:
filters: # The client global filters
- filter1
- filter2
service:
- name: xxx
filters: # The specified remote service filters, which are added after the client global filters
- filter3
server:
filters: # The server global filters
- filter1
- filter2
service:
- name: yyy
filters: # The specified local service filters, which are added after the server global filters
- filter3An example can be found at trpc-java-demo/src/main/resources/trpc_java_server.yaml.
tRPC-Java's plugin mechanism is similar to the Java SPI mechanism, the detailed implementation can
be found
at Plugin Codes
.
The interface annotated with @Extensible is designated as a Plugin interface, as shown below:
@Extensible
public interface WorkerPool {
// ...
}Then, you can create a Plugin class implementing the Plugin interface and annotate it
with @Extension, as shown below:
@Extension("thread")
public class ThreadWorkerPool implements WorkerPool {
// ...
}After writing the Plugin class, you should provide a similar file under META-INF/trpc/ as the
examples showed before in the Filter section.
When you want to use the Plugin, you can get the Plugin instance by using the ExtensionLoader
class as follows:
WorkerPool workerPool=ExtensionLoader.getExtensionLoader(WorkerPool.class).getExtension("thread");
// do with workerPool- Read stub code generation tool to get deeper into
tRPC-Java.