English | 中文
User invoke RPC requests through stub code, and then the request enters client package, where the client package is responsible for the service discovery, interceptor execution, serialization, and compression, and finally, it's sent to the network via the transport package. Upon receiving a network response, the client package executes decompression, deserialization, interceptor execution, and ultimately returns the response to the user. Each step in the client package can be customized, allowing users to define their own service discovery methods, interceptors, serialization, compression, etc.
Users can specify different client options when making RPC requests. These options include the target address, network type, and can also specify the implementation details for each step, such as the service discovery method and serialization method.
proxy := pb.NewGreeterClientProxy()
rsp, err := proxy.Hello(
context.Background(),
&pb.HelloRequest{Msg: "world"},
client.WithTarget("ip://127.0.0.1:9000"), // Specify client options
)
Commonly used options include:
-
WithTarget(target string)
: Set the server address. -
WithNetwork(network string)
: Set the network type. -
WithNamespace(ns string)
: Set the server namespace (Production/Development). -
WithServiceName(name string)
: Set the server service name, which is used for service discovery. -
WithTimeout(timeout time.Duration)
: Set the request timeout. -
WithNamedFilter(name string, f filter.ClientFilter)
: Set client filter. -
WithSerializationType(t int)
: Set the serialization type. Built-in serialization methods include protobuf, JSON, flatbuffer, and custom serialization types can be registered usingcodec.RegisterSerializer
. -
WithCompressType(t int)
: Set the compression type. Built-in compression methods include gzip, snappy, zlib, and custom compression types can be registered usingcodec.RegisterCompressor
. -
WithProtocol(s string)
: Set a custom protocol type (default is trpc), which can be registered usingcodec.Register
.
Users can not only pass client options when making RPC requests but also define client configs in a configuration file. Client options and client configs serve partially overlapping purposes, with client options taking precedence over client configs. When both configs and options are present, the content in the options will override the configs. Using client configs is advantageous as it allows for easy modification of settings without frequent code changes.
client: # Client configs
timeout: 1000 # Timeout(ms) for all requests
namespace: Development # Server environment for all requests
filter: # Filters for all requests
- debuglog # Use debuglog to log request and response
service: # Configs for requests to specific services
- callee: trpc.test.helloworld.Greeter # callee name in the pb protocol file, can be omitted if it matches 'name' below
name: trpc.test.helloworld.Greeter1 # Service name for service discovery
target: ip://127.0.0.1:8000 # Server address, e.g., ip://ip:port or polaris://servicename, can be omitted if using naming discovery with name
network: tcp # Network type for the request (tcp or udp)
protocol: trpc # Application-layer protocol (trpc or http)
timeout: 800 # Request timeout(ms)
serialization: 0 # Serialization type (0-pb, 2-json, 3-flatbuffer); no need to configure by default
compression: 1 # Compression type (1-gzip, 2-snappy, 3-zlib); no need to configure by default
Difference between callee
and name
:
callee
refers to the service name from the pb protocol file, formatted as pbpackage.service
.
For example, if the pb protocol is:
package trpc.a.b;
service Greeter {
rpc SayHello(request) returns reply
}
Then callee
would be trpc.a.b.Greeter
.
name
refers to the service name registered in the naming service. It corresponds to the server.service.name
field in the target service's configuration file.
In most cases, callee
and name
are the same, and you only need to configure one of them. However, in scenarios like storage services where multiple instances of the same pb file are deployed, the service name registered in the naming service may differ from the pb service name. In such cases, you must configure both callee
and name
.
client:
service:
- callee: pbpackage.service # Must configure both callee and name; callee is the pb service name used for matching client proxy and configuration
name: polaris-service-name # Service name in the naming service used for addressing
protocol: trpc
Client-generated stub code from protobuf by default includes the pb service name in the client. Therefore, when the client searches for configurations, it matches them based on the "callee" key, which is the pb service name.
On the other hand, clients generated using constructs like redis.NewClientProxy("trpc.a.b.c")
(including all plugins under the "database" category and HTTP) use the user-provided string as the default service name. Consequently, when searching for configurations, the client utilizes the input parameter of NewClientProxy as the key (e.g., trpc.a.b.c
).
Additionally, the framework supports finding configurations using both "callee" and "name" as keys. For example, in the following two client configurations, they share the same "callee" but have different "name":
client:
service:
- callee: pbpackage.service # "callee" is the pb service name
name: polaris-service-name1 # The service name registered in the naming service for addressing
network: tcp
- callee: pbpackage.service # "callee" is the pb service name
name: polaris-service-name2 # Another service name registered in the naming service for addressing
network: udp
In your code, you can use client.WithServiceName
to find configurations using both callee
and name
as keys:
// proxy1 uses the first configuration, using TCP
proxy1 := pb.NewClientProxy(client.WithServiceName("polaris-service-name1"))
// proxy2 uses the second configuration, using UDP
proxy2 := pb.NewClientProxy(client.WithServiceName("polaris-service-name2"))
- The user submits a request using stub code to invoke an RPC call.
- The request enters the client package.
- Client configurations are completed based on the specified options and configuration file information.
- Service discovery is performed to obtain the actual service address based on the service name.
- Interceptors are invoked, executing the pre-interceptor phase.
- The request body is serialized, resulting in binary data.
- The request body is compressed.
- The complete request is packaged, including the protocol header.
- The transport package sends a network request.
- The transport package receives the network response.
- The response is unpacked to obtain the protocol header and response body.
- The response body is decompressed.
- The response is deserialized to obtain the response structure.
- Interceptors are invoked, executing the post-interceptor phase.
- The response is returned to the user.