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`.