前言
代理 agent
package cluster
定义
文件 agent.go
与用户对应的代理,用于存储原始连接信息
// Agent corresponding a user, used for store raw conn information
agent struct {
// regular agent member
session *session.Session // session
conn net.Conn // low-level conn fd
lastMid uint64 // last message id
state int32 // current agent state
chDie chan struct{} // wait for close
chSend chan pendingMessage // push message queue
lastAt int64 // last heartbeat unix time stamp
decoder *codec.Decoder // binary decoder
pipeline pipeline.Pipeline
rpcHandler rpcHandler
srv reflect.Value // cached session reflect.Value
}
pendingMessage struct {
typ message.Type // message type
route string // message route(push)
mid uint64 // response message id(response)
payload interface{} // payload
}
方法
这个函数循环的处理函数:
func (a *agent) write() {
ticker := time.NewTicker(env.Heartbeat)
chWrite := make(chan []byte, agentWriteBacklog)
// clean func
defer func() {
ticker.Stop()
close(a.chSend)
close(chWrite)
a.Close()
if env.Debug {
log.Println(fmt.Sprintf("Session write goroutine exit, SessionID=%d, UID=%d", a.session.ID(), a.session.UID()))
}
}()
for {
select {
case <-ticker.C:
deadline := time.Now().Add(-2 * env.Heartbeat).Unix()
if atomic.LoadInt64(&a.lastAt) < deadline {
log.Println(fmt.Sprintf("Session heartbeat timeout, LastTime=%d, Deadline=%d", atomic.LoadInt64(&a.lastAt), deadline))
return
}
chWrite <- hbd
case data := <-chWrite:
// close agent while low-level conn broken
if _, err := a.conn.Write(data); err != nil {
log.Println(err.Error())
return
}
case data := <-a.chSend:
payload, err := message.Serialize(data.payload)
if err != nil {
switch data.typ {
case message.Push:
log.Println(fmt.Sprintf("Push: %s error: %s", data.route, err.Error()))
case message.Response:
log.Println(fmt.Sprintf("Response message(id: %d) error: %s", data.mid, err.Error()))
default:
// expect
}
break
}
// construct message and encode
m := &message.Message{
Type: data.typ,
Data: payload,
Route: data.route,
ID: data.mid,
}
if pipe := a.pipeline; pipe != nil {
err := pipe.Outbound().Process(a.session, m)
if err != nil {
log.Println("broken pipeline", err.Error())
break
}
}
em, err := m.Encode()
if err != nil {
log.Println(err.Error())
break
}
// packet encode
p, err := codec.Encode(packet.Data, em)
if err != nil {
log.Println(err)
break
}
chWrite <- p
case <-a.chDie: // agent closed signal
return
case <-env.Die: // application quit
return
}
}
}
下一章
下一章看hander结构