Annuaire d'articles
Préface
Bonjour, je m'appelle Zui Mo Jushi. Notre dernier blog a implémenté la fonction du gestionnaire de tâches. Dans le prochain blog, nous implémenterons le développement du module de distribution de requêtes.
interface
trait/dispatcher.go
type Dispatcher interface {
Start()
Dispatch(connQueue chan Connection)
BatchDispatch(conn Connection) error
SetHeaderDeadline(deadline time.Time)
SetBodyDeadline(deadline time.Time)
ChooseQueue(conn Connection) chan <- Connection
Commit(conn Connection)
}
Structure
gcore/dispatcher.go
// Dispatcher 请求分发模块,负责读取客户端连接的数据,并对数据进行拆包转换成消息格式,然后分发给下游的任务处理模块对消息进行业务处理
type Dispatcher struct {
headerDeadline time.Time
bodyDeadline time.Time
connQueue []chan trait.Connection
taskMgr trait.TaskMgr
}
// NewDispatcher 创建一个请求分发器
func NewDispatcher(taskMgr trait.TaskMgr) *Dispatcher {
connQueue := make([]chan trait.Connection, global.Config.DispatcherQueues)
for i := 0; i < len(connQueue); i++ {
connQueue[i] = make(chan trait.Connection, global.Config.DispatcherQueueLen)
}
return &Dispatcher{
connQueue: connQueue,
taskMgr: taskMgr,
}
}
Implémentation de l'interface
gcore/dispatcher.go
// Start 启动请求分发模块
func (d *Dispatcher) Start() {
for i := 0; i < len(d.connQueue); i++ {
for j := 0; j < global.Config.DispatcherQueueLen; j++ {
go d.Dispatch(d.connQueue[i])
}
}
}
// StartDispatcher 分发连接数据
func (d *Dispatcher) Dispatch(connQueue chan trait.Connection) {
// 从conn中读取数据,并将数据提交给taskMgr处理
for conn := range connQueue {
d.BatchDispatch(conn)
}
}
// BatchDispatch 批量读取连接中的数据,并封装成请求,然后分发请求
func (d *Dispatcher) BatchDispatch(conn trait.Connection) error {
for time.Now().After(d.headerDeadline) {
header := make([]byte, 4)
// 设置header读取超时时间
conn.SetReadDeadline(d.headerDeadline)
_, err := io.ReadFull(conn, header)
if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
// 数据包读取超时
return nil
}
return err
}
// 设置body读取超时时间
conn.SetReadDeadline(d.bodyDeadline)
// 读取长度
dataLen := binary.BigEndian.Uint16(header[2:4])
// 读取数据
body := make([]byte, dataLen)
_, err = io.ReadFull(conn, body)
if err != nil {
return err
}
msg := gpack.Unpack(header, body)
// 提交消息,处理数据
request := NewRequest(conn, msg)
d.taskMgr.Submit(request)
}
return nil
}
// SetHeaderDeadline 设置header读取超时时间
func (d *Dispatcher) SetHeaderDeadline(deadline time.Time) {
d.headerDeadline = deadline
}
// SetBodyDeadline 设置body读取超时时间
func (d *Dispatcher) SetBodyDeadline(deadline time.Time) {
d.bodyDeadline = deadline
}
// ChooseQueue 选择处理连接的队列
func (d *Dispatcher) ChooseQueue(conn trait.Connection) chan <- trait.Connection {
// 负载均衡,选择队列
return d.connQueue[conn.ID() % int32(len(d.connQueue))]
}
// Commit 提交连接到队列
func (d *Dispatcher) Commit(conn trait.Connection) {
d.ChooseQueue(conn) <- conn
}
Adresse du projet
Github : https://github.com/zm50/gte
Github : https://gitee.com/zm50/gte
enfin
Je m'appelle Zui Mo Jushi. Nous avons terminé le développement du distributeur de requêtes de base. J'espère qu'il vous sera utile et que vous gagnerez quelque chose.