Пример #1
0
// 从Client读取数据
func (s *Session) loopReader(tasks chan<- *Request, d Dispatcher) error {
	if d == nil {
		return errors.New("nil dispatcher")
	}

	for !s.quit {
		// client <--> rpc
		// 从client读取frames
		request, err := s.ReadFrame()
		if err != nil {
			err1, ok := err.(thrift.TTransportException)
			if !ok || err1.TypeId() != thrift.END_OF_FILE {
				// 遇到EOF等错误,就直接结束loopReader
				// 结束之前需要和后端的back_conn之间处理好关系?
				log.ErrorErrorf(err, Red("ReadFrame Error: %v"), err)
			}
			return err
		}

		r, err := s.handleRequest(request, d)
		if err != nil {
			return err
		} else {
			if s.verbose {
				log.Info("Succeed Get Result")
			}

			// 将请求交给: tasks, 同一个Session中的请求是
			tasks <- r
		}
	}
	return nil
}
Пример #2
0
// 配对 Request, resp, err
// PARAM: resp []byte 为一帧完整的thrift数据包
func (bc *BackendConnLB) setResponse(r *Request, data []byte, err error) error {
	// 表示出现错误了
	if data == nil {
		log.Printf("No Data From Server, error: %v\n", err)
		r.Response.Err = err
	} else {
		// 从resp中读取基本的信息
		typeId, seqId, err := DecodeThriftTypIdSeqId(data)

		// 解码错误,直接报错
		if err != nil {
			return err
		}

		if typeId == MESSAGE_TYPE_STOP {
			// 不再接受新的输入
			// 直接来自后端的服务(不遵循: Request/Reply模型)
			bc.MarkConnActiveFalse()
			return nil
		}

		// 找到对应的Request
		bc.Lock()
		req, ok := bc.seqNum2Request[seqId]
		if ok {
			delete(bc.seqNum2Request, seqId)
		}
		bc.Unlock()

		// 如果是心跳,则OK
		if typeId == MESSAGE_TYPE_HEART_BEAT {
			bc.hbLastTime.Set(time.Now().Unix())
			return nil
		}

		if !ok {
			return errors.New("Invalid Response")
		}

		//		log.Printf("Data From Server, seqId: %d, Request: %d\n", seqId, req.Request.SeqId)
		r = req
		r.Response.TypeId = typeId
	}

	r.Response.Data, r.Response.Err = data, err
	// 还原SeqId
	if data != nil {
		r.RestoreSeqId()
	}

	// 设置几个控制用的channel
	if err != nil && r.Failed != nil {
		r.Failed.Set(true)
	}
	if r.Wait != nil {
		r.Wait.Done()
	}

	return err
}
Пример #3
0
// 配对 Request, resp, err
// PARAM: resp []byte 为一帧完整的thrift数据包
func (bc *BackendConn) setResponse(r *Request, data []byte, err error) error {
	// 表示出现错误了
	if data == nil {
		log.Printf("[%s]No Data From Server, error: %v", r.Service, err)
		r.Response.Err = err
	} else {
		// 从resp中读取基本的信息
		typeId, seqId, err := DecodeThriftTypIdSeqId(data)

		// 解码错误,直接报错
		if err != nil {
			return err
		}

		// 找到对应的Request
		bc.Lock()
		req, ok := bc.seqNum2Request[seqId]
		if ok {
			delete(bc.seqNum2Request, seqId)
		}
		bc.Unlock()

		// 如果是心跳,则OK
		if typeId == MESSAGE_TYPE_HEART_BEAT {
			//			log.Printf(Magenta("Get Ping/Pang Back"))
			bc.hbLastTime.Set(time.Now().Unix())
			return nil
		}

		if !ok {
			return errors.New("Invalid Response")
		}
		if bc.verbose {
			log.Printf("[%s]Data From Server, seqId: %d, Request: %d", req.Service, seqId, req.Request.SeqId)
		}
		r = req
		r.Response.TypeId = typeId
	}

	r.Response.Data, r.Response.Err = data, err

	// 还原SeqId
	if data != nil {
		r.RestoreSeqId()
	}

	// 设置几个控制用的channel
	if err != nil && r.Failed != nil {
		r.Failed.Set(true)
	}
	if r.Wait != nil {
		r.Wait.Done()
	}

	return err
}
Пример #4
0
const (
	B = 1 << (10 * iota)
	KB
	MB
	GB
	TB
	PB
)

var (
	BytesizeRegexp = regexp.MustCompile(`(?i)^\s*(\-?[\d\.]+)\s*([KMGTP]?B|[BKMGTP]|)\s*$`)
	digitsRegexp   = regexp.MustCompile(`^\-?\d+$`)
)

var (
	ErrBadBytesize     = errors.New("invalid byte size")
	ErrBadBytesizeUnit = errors.New("invalid byte size unit")
)

func Parse(s string) (int64, error) {
	if !BytesizeRegexp.MatchString(s) {
		return 0, errors.Trace(ErrBadBytesize)
	}

	subs := BytesizeRegexp.FindStringSubmatch(s)
	if len(subs) != 3 {
		return 0, errors.Trace(ErrBadBytesize)
	}

	size := int64(0)
	switch strings.ToUpper(string(subs[2])) {
Пример #5
0
//
// 将 bc.input 中的Request写入后端的服务器
//
func (bc *BackendConn) loopWriter(c *TBufferedFramedTransport) error {

	bc.hbTicker = time.NewTicker(time.Second)
	defer func() {
		bc.hbTicker.Stop()
		bc.hbStop <- true
	}()

	bc.MarkConnActiveOK() // 准备接受数据
	bc.loopReader(c)      // 异步
	bc.Heartbeat()        // 建立连接之后,就启动HB

	var r *Request
	var ok bool

	for true {
		// 等待输入的Event, 或者 heartbeatTimeout
		select {
		case r, ok = <-bc.input:
			if !ok {
				return nil
			}
		case <-bc.hbTimeout:
			return errors.New(fmt.Sprintf("[%s]HB timeout", bc.service))
		}

		//
		// 如果暂时没有数据输入,则p策略可能就有问题了
		// 只有写入数据,才有可能产生flush; 如果是最后一个数据必须自己flush, 否则就可能无限期等待
		//
		if r.Request.TypeId == MESSAGE_TYPE_HEART_BEAT {
			// 过期的HB信号,直接放弃
			if time.Now().Unix()-r.Start > 4 {
				continue
			}
		}

		// 请求正常转发给后端的Rpc Server
		var flush = len(bc.input) == 0
		//		if bc.verbose {
		//			fmt.Printf("Force flush %t", flush)
		//		}

		// 1. 替换新的SeqId
		r.ReplaceSeqId(bc.currentSeqId)

		// 2. 主动控制Buffer的flush
		c.Write(r.Request.Data)
		err := c.FlushBuffer(flush)

		if err == nil {
			//			log.Printf("Succeed Write Request to backend Server/LB\n")
			bc.IncreaseCurrentSeqId()
			bc.Lock()
			bc.seqNum2Request[r.Response.SeqId] = r
			bc.Unlock()

		} else {
			// 进入不可用状态(不可用状态下,通过自我心跳进入可用状态)
			return bc.setResponse(r, nil, err)
		}
	}

	return nil
}
Пример #6
0
func NewRollingFile(basePath string, logKeepDays int) (io.WriteCloser, error) {
	if logKeepDays <= 0 {
		return nil, errors.Errorf("invalid max file-frag = %d", logKeepDays)
	}
	if _, file := path.Split(basePath); file == "" {
		return nil, errors.Errorf("invalid base-path = %s, file name is required", basePath)
	}

	return &rollingFile{
		logKeepDays:     logKeepDays,
		basePath:        basePath,
		nextStartOfDate: nextStartOfDay(time.Now()),
	}, nil
}

var ErrClosedRollingFile = errors.New("rolling file is closed")

func (r *rollingFile) roll() error {
	if r.file != nil {
		// 还没有日期切换
		now := time.Now()
		if now.Before(r.nextStartOfDate) {
			return nil
		}
		r.file.Close()
		r.file = nil
		r.nextStartOfDate = nextStartOfDay(now)

		// 将logKeepDays之前几天的日志删除
		for i := r.logKeepDays; i < r.logKeepDays+4; i++ {
Пример #7
0
//
// 数据: LB ---> backend services
//
// 如果input关闭,且loopWriter正常处理完毕之后,返回nil
// 其他情况返回error
//
func (bc *BackendConnLB) loopWriter() error {
	// 正常情况下, ok总是为True; 除非bc.input的发送者主动关闭了channel, 表示再也没有新的Task过来了
	// 参考: https://tour.golang.org/concurrency/4
	// 如果input没有关闭,则会block
	c := NewTBufferedFramedTransport(bc.transport, 100*time.Microsecond, 20)

	// bc.MarkConnActiveOK() // 准备接受数据
	// BackendConnLB 在构造之初就有打开的transport, 并且Active默认为OK

	bc.hbTicker = time.NewTicker(time.Second)
	defer func() {
		bc.hbTicker.Stop()
		bc.hbStop <- true
	}()

	bc.loopReader(c) // 异步
	bc.Heartbeat()   // 建立连接之后,就启动HB

	var r *Request
	var ok bool

	for true {
		// 等待输入的Event, 或者 heartbeatTimeout
		select {
		case r, ok = <-bc.input:
			if !ok {
				return nil
			}
		case <-bc.hbTimeout:
			return errors.New("HB timeout")
		}

		// 如果暂时没有数据输入,则p策略可能就有问题了
		// 只有写入数据,才有可能产生flush; 如果是最后一个数据必须自己flush, 否则就可能无限期等待
		//
		if r.Request.TypeId == MESSAGE_TYPE_HEART_BEAT {
			// 过期的HB信号,直接放弃
			if time.Now().Unix()-r.Start > 4 {
				continue
			} else {
				//					log.Printf(Magenta("Send Heartbeat to %s\n"), bc.Addr4Log())
			}
		}
		var flush = len(bc.input) == 0
		//		fmt.Printf("Force flush %t\n", flush)

		// 1. 替换新的SeqId
		r.ReplaceSeqId(bc.currentSeqId)

		// 2. 主动控制Buffer的flush

		//			log.Printf("Request Data Len: %d\n ", len(r.Request.Data))
		c.Write(r.Request.Data)
		err := c.FlushBuffer(flush)

		if err == nil {

			bc.IncreaseCurrentSeqId()
			bc.Lock()
			bc.seqNum2Request[r.Response.SeqId] = r
			bc.Unlock()

			// 继续读取请求, 如果有异常,如何处理呢?
		} else {
			log.ErrorErrorf(err, "FlushBuffer Error: %v\n", err)

			// 进入不可用状态(不可用状态下,通过自我心跳进入可用状态)
			return bc.setResponse(r, nil, err)
		}
	}
	return nil
}