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  }