trpc.group/trpc-go/trpc-go@v1.0.3/docs/user_guide/reverse_proxy.md (about)

     1  English | [中文](reverse_proxy.zh_CN.md)
     2  
     3  # tRPC-Go Reverse Proxy
     4  
     5  ## Introduction
     6  
     7  In some special scenarios, such as reverse proxy forwarding services, where fully transitive binary body data is required without serializing (and deserializing) requests (and responses) to improve forwarding performance, tRPC-Go provides support for these scenarios as well by providing custom serialization methods.
     8  
     9  ## Implementation
    10  
    11  ### Pass-through Server
    12  
    13  Pass-through server takes out the binary body directly to the handler function when it receives the request, without deserialization, and packs the binary body directly to the upstream when it returns the packet, without serialization.
    14  
    15  #### Custom stub code
    16  
    17  Since there is no serialization and deserialization process, i.e. no pb protocol file, users need to write their own service stub code and processing functions.
    18  The key point is to use `codec.Body` (or implement BytesBodyIn BytesBodyOut interface, see [here](https://github.com/trpc-group/trpc-go/blob/ed918a35b8318d59afc4363d9a2a09bfcac75ab9/codec/serialization_noop.go#L26)) to pass through the binary, use `wildcards*` for forwarding, and execute the interceptors by yourself.
    19  
    20  ```go
    21  type AccessServer interface {
    22      Forward(ctx context.Context, reqbody *codec.Body) (rspbody *codec.Body, err error)
    23  }
    24  
    25  // AccessServer_Forward_Handler is a message handling callback function. 
    26  func AccessServer_Forward_Handler(svr interface{}, ctx context.Context, f server.FilterFunc) (rspbody interface{}, err error) {
    27      req := &codec.Body{}
    28      filters, err := f(req)
    29      if err != nil {
    30          return nil, err
    31      }
    32      handleFunc := func(ctx context.Context, reqbody interface{}) (rspbody interface{}, err error) {
    33          return svr.(AccessServer).Forward(ctx, reqbody.(*codec.Body))
    34      }
    35      var rsp interface{}
    36      rsp, err = filters.Filter(ctx, req, handleFunc)
    37      if err ! = nil {
    38          return nil, err
    39      }
    40      return rsp, nil
    41  }
    42  
    43  // AccessServer_ServiceDesc describes service description information, and use wildcards * for forwarding.
    44  var AccessServer_ServiceDesc = server.ServiceDesc{
    45      ServiceName: "trpc.app.server.Access",
    46      HandlerType: ((*AccessServer)(nil)), 
    47      Methods: []server.Method{
    48          server.Method{
    49              Name: "*", 
    50              Func: AccessServer_Forward_Handler,
    51          },
    52      },
    53  }
    54  
    55  // RegisterAccessService registers the service.
    56  func RegisterAccessService(s server.Service, svr AccessServer) {
    57      s.Register(&AccessServer_ServiceDesc, svr)
    58  }
    59  ```
    60  
    61  #### Specifying the empty serialization method
    62  
    63  After defining the stub code, you can implement the handler function and start the service. 
    64  The key point is to pass `WithCurrentSerializationType(codec.SerializationTypeNoop)` when you are calling `NewServer` to tell the framework that the current message is only transmitted and not serialized.
    65  
    66  ```go
    67  type AccessServerImpl struct{}
    68  
    69  // Forward implements forwarding proxy logic
    70  func (s *AccessServerImpl) Forward(ctx context.Context, reqbody *codec.Body) (rspbody *codec.Body, err error) {
    71      // Your own internal processing logic
    72  }
    73  
    74  func main() {
    75      s := trpc.NewServer(
    76          server.WithCurrentSerializationType(codec.SerializationTypeNoop).
    77      ) // No serialization
    78      
    79      RegisterAccessService(s, &AccessServerImpl{})
    80  
    81      if err := s.Serve(); err ! = nil { 
    82          panic(err) 
    83      } 
    84  }
    85  ```
    86  
    87  ### Pass-through Client
    88  
    89  Pass-through Client packages and sends out the binary body directly when the rpc request is made to the downstream, without serialization, and is returned directly after the packet is returned, without deserialization.
    90  
    91  #### Specifying the empty serialization method
    92  
    93  Although the current framework is not serialized, but still need to tell the downstream the current binary has been packaged by what serialization method, because the downstream need to parse through this serialization method, so you should set `WithSerializationType` ` WithCurrentSerializationType` these two options.
    94  
    95  ```go
    96  ctx, msg := codec.WithCloneMessage(ctx) // copy a ctx, generate caller callee and other information, easy to monitor the framework to report
    97  msg.WithClientRPCName("/trpc.test.helloworld.Greeter/SayHello") // set the downstream method name
    98  msg.WithCalleeServiceName("trpc.test.helloworld.Greeter") // set the downstream service name
    99  callopts := []client.Option{
   100      client.WithProtocol("trpc").
   101      client.WithSerializationType(codec.SerializationTypePB), // tell downstream that the current body has been serialized with pb
   102      WithCurrentSerializationType(codec.SerializationTypeNoop), // tells the framework that the current client is only transitive and not serialized
   103  }
   104  
   105  req := &codec.Body{Data: []byte("I am a binary data that has been packaged by other serialization methods")}
   106  rsp := &codec.Body{} // After the packetization, the framework will automatically fill this rsp.Data with binary data
   107  DefaultClient.Invoke(ctx, req, rsp, callopts...) // req rsp is the binary data that the user has already serialized himself
   108  if err ! = nil {
   109      return err
   110  }
   111  ```
   112  
   113  ## FAQ
   114  
   115  ### Q1: SerializationType and CurrentSerializationType what do these two options mean and what is the difference
   116  
   117  tRPC-Go provides `SerializationType` and `CurrentSerializationType` to support proxy forwarding.
   118  
   119  SerializationType is mainly used for context passing of network calls, and CurrentSerializationType is mainly used for current framework data parsing.
   120  `SerializationType` refers to the original serialization method of the body, which is normally specified inside the protocol field. 
   121  tRPC default serialization type is pb.
   122  `CurrentSerializationType` refers to the framework received data, the real way to perform serialization operations, generally do not need to fill in, and the default is equal to SerializationType.
   123  CurrentSerializationType allows users to set their own arbitrary serialization method, In above reverse proxy example CurrentSerializationType is set to `NoopSerializationType`.