github.com/matrixorigin/matrixone@v0.7.0/pkg/txn/rpc/server.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package rpc 16 17 import ( 18 "context" 19 "sync" 20 21 "github.com/fagongzi/goetty/v2" 22 "github.com/matrixorigin/matrixone/pkg/common/morpc" 23 "github.com/matrixorigin/matrixone/pkg/common/mpool" 24 "github.com/matrixorigin/matrixone/pkg/common/runtime" 25 "github.com/matrixorigin/matrixone/pkg/pb/txn" 26 "github.com/matrixorigin/matrixone/pkg/util/trace" 27 "go.uber.org/zap" 28 ) 29 30 // WithServerMaxMessageSize set max rpc message size 31 func WithServerMaxMessageSize(maxMessageSize int) ServerOption { 32 return func(s *server) { 33 s.options.maxMessageSize = maxMessageSize 34 } 35 } 36 37 // WithServerEnableCompress enable compress 38 func WithServerEnableCompress(enable bool) ServerOption { 39 return func(s *server) { 40 s.options.enableCompress = enable 41 } 42 } 43 44 // set filter func. Requests can be modified or filtered out by the filter 45 // before they are processed by the handler. 46 func WithServerMessageFilter(filter func(*txn.TxnRequest) bool) ServerOption { 47 return func(s *server) { 48 s.options.filter = filter 49 } 50 } 51 52 type server struct { 53 rt runtime.Runtime 54 rpc morpc.RPCServer 55 handlers map[txn.TxnMethod]TxnRequestHandleFunc 56 57 pool struct { 58 requests sync.Pool 59 responses sync.Pool 60 } 61 62 options struct { 63 filter func(*txn.TxnRequest) bool 64 maxMessageSize int 65 enableCompress bool 66 } 67 } 68 69 // NewTxnServer create a txn server. One DNStore corresponds to one TxnServer 70 func NewTxnServer( 71 address string, 72 rt runtime.Runtime, 73 opts ...ServerOption) (TxnServer, error) { 74 s := &server{ 75 rt: rt, 76 handlers: make(map[txn.TxnMethod]TxnRequestHandleFunc), 77 } 78 s.pool.requests = sync.Pool{ 79 New: func() any { 80 return &txn.TxnRequest{} 81 }, 82 } 83 s.pool.responses = sync.Pool{ 84 New: func() any { 85 return &txn.TxnResponse{} 86 }, 87 } 88 for _, opt := range opts { 89 opt(s) 90 } 91 92 var codecOpts []morpc.CodecOption 93 codecOpts = append(codecOpts, 94 morpc.WithCodecIntegrationHLC(rt.Clock()), 95 morpc.WithCodecEnableChecksum(), 96 morpc.WithCodecPayloadCopyBufferSize(16*1024), 97 morpc.WithCodecMaxBodySize(s.options.maxMessageSize)) 98 if s.options.enableCompress { 99 mp, err := mpool.NewMPool("txn_rpc_server", 0, mpool.NoFixed) 100 if err != nil { 101 return nil, err 102 } 103 codecOpts = append(codecOpts, morpc.WithCodecEnableCompress(mp)) 104 } 105 rpc, err := morpc.NewRPCServer("txn-server", address, 106 morpc.NewMessageCodec(s.acquireRequest, 107 codecOpts...), 108 morpc.WithServerLogger(s.rt.Logger().RawLogger()), 109 morpc.WithServerGoettyOptions(goetty.WithSessionReleaseMsgFunc(func(v interface{}) { 110 m := v.(morpc.RPCMessage) 111 if !m.InternalMessage() { 112 s.releaseResponse(m.Message.(*txn.TxnResponse)) 113 } 114 }))) 115 if err != nil { 116 return nil, err 117 } 118 119 rpc.RegisterRequestHandler(s.onMessage) 120 s.rpc = rpc 121 return s, nil 122 } 123 124 func (s *server) Start() error { 125 return s.rpc.Start() 126 } 127 128 func (s *server) Close() error { 129 return s.rpc.Close() 130 } 131 132 func (s *server) RegisterMethodHandler(m txn.TxnMethod, h TxnRequestHandleFunc) { 133 s.handlers[m] = h 134 } 135 136 // onMessage a client connection has a separate read goroutine. The onMessage invoked in this read goroutine. 137 func (s *server) onMessage(ctx context.Context, request morpc.Message, sequence uint64, cs morpc.ClientSession) error { 138 ctx, span := trace.Debug(ctx, "server.onMessage") 139 defer span.End() 140 m, ok := request.(*txn.TxnRequest) 141 if !ok { 142 s.rt.Logger().Fatal("received invalid message", zap.Any("message", request)) 143 } 144 defer s.releaseRequest(m) 145 146 if s.options.filter != nil && !s.options.filter(m) { 147 return nil 148 } 149 150 handler, ok := s.handlers[m.Method] 151 if !ok { 152 s.rt.Logger().Fatal("missing txn request handler", 153 zap.String("method", m.Method.String())) 154 } 155 156 select { 157 case <-ctx.Done(): 158 return nil 159 default: 160 } 161 162 resp := s.acquireResponse() 163 if err := handler(ctx, m, resp); err != nil { 164 s.releaseResponse(resp) 165 return err 166 } 167 168 resp.RequestID = m.RequestID 169 return cs.Write(ctx, resp) 170 } 171 172 func (s *server) acquireResponse() *txn.TxnResponse { 173 return s.pool.responses.Get().(*txn.TxnResponse) 174 } 175 176 func (s *server) releaseResponse(resp *txn.TxnResponse) { 177 resp.Reset() 178 s.pool.responses.Put(resp) 179 } 180 181 func (s *server) acquireRequest() morpc.Message { 182 return s.pool.requests.Get().(*txn.TxnRequest) 183 } 184 185 func (s *server) releaseRequest(req *txn.TxnRequest) { 186 req.Reset() 187 s.pool.requests.Put(req) 188 }