Ejemplo n.º 1
0
// 处理所有的等待中的请求
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)
	}

}
Ejemplo n.º 2
0
//
// 后端如何处理一个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
}
Ejemplo n.º 3
0
// 配对 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
}
Ejemplo n.º 4
0
//
// 将 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
}
Ejemplo n.º 5
0
// 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()
	}
}