// 处理所有的等待中的请求 func (bc *BackendConn) flushRequests(err error) { // 告诉BackendService, 不再接受新的请求 bc.MarkConnActiveFalse() seqRequest := bc.seqNumRequestMap.Purge() for _, request := range seqRequest { request.Response.Err = err request.Wait.Done() log.Debugf("FlushRequests, SeqId: %d", request.Response.SeqId) } }
// // 后端如何处理一个Request // func (p *ThriftRpcServer) Dispatch(r *Request) error { transport := NewTMemoryBufferWithBuf(r.Request.Data) ip := thrift.NewTBinaryProtocolTransport(transport) slice := getSlice(0, DEFAULT_SLICE_LEN) transport = NewTMemoryBufferWithBuf(slice) op := thrift.NewTBinaryProtocolTransport(transport) p.Processor.Process(ip, op) r.Response.Data = transport.Bytes() _, _, seqId, _ := DecodeThriftTypIdSeqId(r.Response.Data) log.Debugf("SeqId: %d vs. %d, Dispatch Over", r.Request.SeqId, seqId) // // 如果transport重新分配了内存,则立即归还slice // if cap(r.Response.Data) != DEFAULT_SLICE_LEN { // returnSlice(slice) // } return nil }
// 配对 Request, resp, err // PARAM: resp []byte 为一帧完整的thrift数据包 func (bc *BackendConn) setResponse(r *Request, data []byte, err error) error { // 表示出现错误了 if data == nil { log.Debugf("[%s] SeqId: %d, No Data From Server, error: %v", r.Service, r.Response.SeqId, err) r.Response.Err = err } else { // 从resp中读取基本的信息 typeId, method, seqId, err := DecodeThriftTypIdSeqId(data) // if err != nil { // log.Debugf("SeqId: %d, Decoded, error: %v", seqId, err) // } else { // log.Debugf("SeqId: %d, Decoded", seqId) // } // 解码错误,直接报错 if err != nil { log.Debugf("SeqId: %d, Decoded, error: %v", seqId, err) return err } // 找到对应的Request req := bc.seqNumRequestMap.Pop(seqId) // 如果是心跳,则OK if typeId == MESSAGE_TYPE_HEART_BEAT { bc.hbLastTime.Set(time.Now().Unix()) // if req != nil { // log.Printf("HB RT: %.3fms", float64(microseconds()-req.Start)*0.001) // } return nil } if req == nil { // return errors.New("Invalid Response") // 由于是异步返回,因此回来找不到也正常 log.Errorf("#setResponse not found, seqId: %d", seqId) return nil } else { if req.Response.SeqId != seqId { log.Errorf("Data From Server, SeqId not match, Ex: %d, Ret: %d", req.Request.SeqId, seqId) } r = req r.Response.TypeId = typeId if req.Request.Name != method { data = nil err = req.NewInvalidResponseError(method, "conn_proxy") } } } // 正常返回数据,或者报错 r.Response.Data, r.Response.Err = data, err // 还原SeqId if data != nil { r.RestoreSeqId() } // 设置几个控制用的channel r.Wait.Done() return err }
// // 将 bc.input 中的Request写入后端的服务器 // func (bc *BackendConn) loopWriter(c *TBufferedFramedTransport) error { defer func() { // 关闭心跳的Ticker bc.hbTicker.Stop() bc.hbTicker = nil }() var r *Request var ok bool // 准备HB Ticker bc.hbTicker = time.NewTicker(time.Second) bc.hbLastTime.Set(time.Now().Unix()) for true { // 等待输入的Event, 或者 heartbeatTimeout select { case <-bc.hbTicker.C: if time.Now().Unix()-bc.hbLastTime.Get() > HB_TIMEOUT { return errors.New(fmt.Sprintf("[%s]HB timeout", bc.service)) } else { // 定时添加Ping的任务; 如果标记下线,则不在心跳 if !bc.IsMarkOffline.Get() { // 发送心跳信息 r := NewPingRequest() bc.PushBack(r) // 同时检测当前的异常请求 expired := microseconds() - REQUEST_EXPIRED_TIME_MICRO // 以microsecond为单位 // microseconds() - request.Start > REQUEST_EXPIRED_TIME_MICRO // 超时: microseconds() - REQUEST_EXPIRED_TIME_MICRO > request.Start bc.seqNumRequestMap.RemoveExpired(expired) } } case r, ok = <-bc.input: if !ok { return nil } else { // // 如果暂时没有数据输入,则p策略可能就有问题了 // 只有写入数据,才有可能产生flush; 如果是最后一个数据必须自己flush, 否则就可能无限期等待 // if r.Request.TypeId == MESSAGE_TYPE_HEART_BEAT { // 过期的HB信号,直接放弃 if time.Now().Unix()-r.Start > 4 { log.Printf(Magenta("Expired HB Signal")) } } // 请求正常转发给后端的Rpc Server var flush = len(bc.input) == 0 // 1. 替换新的SeqId r.ReplaceSeqId(bc.currentSeqId) bc.IncreaseCurrentSeqId() // 2. 主动控制Buffer的flush // 先记录SeqId <--> Request, 再发送请求 // 否则: 请求从后端返回,记录还没有完成,就容易导致Request丢失 bc.seqNumRequestMap.Add(r.Response.SeqId, r) // 2. 主动控制Buffer的flush c.Write(r.Request.Data) err := c.FlushBuffer(flush) if err == nil { log.Debugf("--> SeqId: %d vs. %d To Backend", r.Request.SeqId, r.Response.SeqId) } else { bc.seqNumRequestMap.Pop(r.Response.SeqId) // 如果写错了,在删除 // 进入不可用状态(不可用状态下,通过自我心跳进入可用状态) return bc.setResponse(r, nil, err) } } } } return nil }
// Session是同步处理请求,因此没有必要搞多个 func (s *Session) Serve(d Dispatcher, maxPipeline int) { defer func() { s.Close() log.Infof(Red("==> Session Over: %s, Total %d Ops"), s.RemoteAddress, s.Ops) if err := recover(); err != nil { log.Infof(Red("Catch session error: %v"), err) } }() for true { // 1. 读取请求 request, err := s.ReadFrame() s.Ops += 1 // 读取出错,直接退出 if err != nil { err1, ok := err.(thrift.TTransportException) if !ok || err1.TypeId() != thrift.END_OF_FILE { log.ErrorErrorf(err, Red("ReadFrame Error: %v"), err) } // r.Recycle() return } var r *Request // 2. 处理请求 r, err = s.handleRequest(request, d) if err != nil { // r.Recycle() // 出错之后也要主动返回数据 log.ErrorErrorf(err, Red("handleRequest Error: %v"), err) r.Response.Err = err } // 3. 等待请求处理完毕 s.handleResponse(r) // 4. 将结果写回给Client if s.verbose { log.Debugf("[%s]Session#loopWriter --> client FrameSize: %d", r.Service, len(r.Response.Data)) } // 5. 将请求返回给Client, r.Response.Data ---> Client _, err = s.TBufferedFramedTransport.Write(r.Response.Data) r.Recycle() // 重置: Request if err != nil { log.ErrorErrorf(err, "Write back Data Error: %v", err) return } // 6. Flush err = s.TBufferedFramedTransport.FlushBuffer(true) // len(tasks) == 0 if err != nil { log.ErrorErrorf(err, "Write back Data Error: %v", err) return } // r.Recycle() } }