trpc.group/trpc-go/trpc-go@v1.0.3/client/README.md (about)

     1  English | [中文](README.zh_CN.md)
     2  
     3  # tRPC-Go Client Package
     4  
     5  
     6  ## Background
     7  
     8  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.
     9  
    10  ## Client Options
    11  
    12  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.
    13  
    14  ```golang
    15  proxy := pb.NewGreeterClientProxy()
    16  rsp, err := proxy.Hello(
    17      context.Background(),
    18      &pb.HelloRequest{Msg: "world"},
    19      client.WithTarget("ip://127.0.0.1:9000"), // Specify client options
    20  )
    21  ```
    22  
    23  Commonly used options include:
    24  
    25  - `WithTarget(target string)`: Set the server address.
    26  
    27  - `WithNetwork(network string)`: Set the network type.
    28  
    29  - `WithNamespace(ns string)`: Set the server namespace (Production/Development).
    30  
    31  - `WithServiceName(name string)`: Set the server service name, which is used for service discovery.
    32  
    33  - `WithTimeout(timeout time.Duration)`: Set the request timeout.
    34  
    35  - `WithNamedFilter(name string, f filter.ClientFilter)`: Set client filter.
    36  
    37  - `WithSerializationType(t int)`: Set the serialization type. Built-in serialization methods include protobuf, JSON, flatbuffer, and custom serialization types can be registered using `codec.RegisterSerializer`.
    38  
    39  - `WithCompressType(t int)`: Set the compression type. Built-in compression methods include gzip, snappy, zlib, and custom compression types can be registered using `codec.RegisterCompressor`.
    40  
    41  - `WithProtocol(s string)`: Set a custom protocol type (default is trpc), which can be registered using `codec.Register`.
    42  
    43  ## Client Configs
    44  
    45  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.
    46  
    47  ```yaml
    48  client: # Client configs
    49    timeout: 1000 # Timeout(ms) for all requests
    50    namespace: Development # Server environment for all requests
    51    filter: # Filters for all requests
    52      - debuglog # Use debuglog to log request and response
    53    service: # Configs for requests to specific services
    54      - callee: trpc.test.helloworld.Greeter # callee name in the pb protocol file, can be omitted if it matches 'name' below
    55        name: trpc.test.helloworld.Greeter1 # Service name for service discovery
    56        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
    57        network: tcp # Network type for the request (tcp or udp)
    58        protocol: trpc # Application-layer protocol (trpc or http)
    59        timeout: 800 # Request timeout(ms)
    60        serialization: 0 # Serialization type (0-pb, 2-json, 3-flatbuffer); no need to configure by default
    61        compression: 1 # Compression type (1-gzip, 2-snappy, 3-zlib); no need to configure by default
    62  ```
    63  
    64  Difference between `callee` and `name`:
    65  
    66  **`callee` refers to the service name from the pb protocol file, formatted as `pbpackage.service`.**
    67  
    68  For example, if the pb protocol is:
    69  
    70  ```protobuf
    71  package trpc.a.b;
    72  service Greeter {
    73      rpc SayHello(request) returns reply
    74  }
    75  ```
    76  
    77  Then `callee` would be `trpc.a.b.Greeter`.
    78  
    79  **`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.
    80  
    81  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`.
    82  
    83  ```yaml
    84  client:
    85    service:
    86      - callee: pbpackage.service # Must configure both callee and name; callee is the pb service name used for matching client proxy and configuration
    87        name: polaris-service-name # Service name in the naming service used for addressing
    88        protocol: trpc
    89  ```
    90  
    91  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.
    92  
    93  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`).
    94  
    95  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":
    96  
    97  ```yaml
    98  client:
    99    service:
   100      - callee: pbpackage.service # "callee" is the pb service name
   101        name: polaris-service-name1 # The service name registered in the naming service for addressing
   102        network: tcp
   103      - callee: pbpackage.service # "callee" is the pb service name
   104        name: polaris-service-name2 # Another service name registered in the naming service for addressing
   105        network: udp
   106  ```
   107  
   108  In your code, you can use `client.WithServiceName` to find configurations using both `callee` and `name` as keys:
   109  
   110  ```golang
   111  // proxy1 uses the first configuration, using TCP
   112  proxy1 := pb.NewClientProxy(client.WithServiceName("polaris-service-name1"))
   113  // proxy2 uses the second configuration, using UDP
   114  proxy2 := pb.NewClientProxy(client.WithServiceName("polaris-service-name2"))
   115  ```
   116  
   117  ## Client Invocation Workflow
   118  
   119  1. The user submits a request using stub code to invoke an RPC call.
   120  2. The request enters the client package.
   121  3. Client configurations are completed based on the specified options and configuration file information.
   122  4. Service discovery is performed to obtain the actual service address based on the service name.
   123  5. Interceptors are invoked, executing the pre-interceptor phase.
   124  6. The request body is serialized, resulting in binary data.
   125  7. The request body is compressed.
   126  8. The complete request is packaged, including the protocol header.
   127  9. The transport package sends a network request.
   128  10. The transport package receives the network response.
   129  11. The response is unpacked to obtain the protocol header and response body.
   130  12. The response body is decompressed.
   131  13. The response is deserialized to obtain the response structure.
   132  14. Interceptors are invoked, executing the post-interceptor phase.
   133  15. The response is returned to the user.