Przeglądaj źródła

add connect lock mutex

Joyit 3 miesięcy temu
rodzic
commit
e6af341a47
4 zmienionych plików z 17 dodań i 14 usunięć
  1. 1 0
      README.md
  2. 0 1
      conn/tcp2/tcp2.go
  3. 15 12
      hub.go
  4. 1 1
      line.go

+ 1 - 0
README.md

@@ -31,6 +31,7 @@
 - 优化命令匹配的算法,当有数量级的连接时需要考虑;如使用固定 ID,自动生成匹配缓存等方式
 - 建立内存池来分配内存,减少内存碎片
 - 同地址多连接共存,使用不同的连接发送消息,减少延时,提高消息送达可靠性
+- 并发相同channel连接时出现竞争的情况
 
 ## 已经解决的问题
 

+ 0 - 1
conn/tcp2/tcp2.go

@@ -490,7 +490,6 @@ func (c *Tcp2) WritePing(id uint16) error {
 	buf, start := c.writeDataLen(dlen)
 	index := start
 	binary.BigEndian.PutUint16(buf[index:index+2], id)
-	// index += 2
 	buf[start+dlen] = util.CRC8(buf[start : start+dlen])
 	return c.writeMessage(buf)
 }

+ 15 - 12
hub.go

@@ -34,16 +34,17 @@ func subStr(str string, length int) string {
 }
 
 type Hub struct {
-	sync.Mutex
-	ctx        context.Context // 为了方便退出而建立
-	cancel     context.CancelFunc
-	cf         *config.Config
-	globalID   uint16
-	channel    string       // 本地频道信息
-	middle     []MiddleFunc // 中间件
-	lines      *Mapx        // 记录当前的连接,统一管理
-	subscribes sync.Map     // [cmd]->[]*SubscribeData   //注册绑定频道的函数,用于响应请求
-	msgCache   sync.Map     //  map[uint16]*GetMsg //请求的回应记录,key为id
+	ctx          context.Context // 为了方便退出而建立
+	cancel       context.CancelFunc
+	cf           *config.Config
+	connectMutex sync.Mutex
+	idMutex      sync.Mutex
+	globalID     uint16
+	channel      string       // 本地频道信息
+	middle       []MiddleFunc // 中间件
+	lines        *Mapx        // 记录当前的连接,统一管理
+	subscribes   sync.Map     // [cmd]->[]*SubscribeData   //注册绑定频道的函数,用于响应请求
+	msgCache     sync.Map     //  map[uint16]*GetMsg //请求的回应记录,key为id
 
 	// 客户端需要用的函数(服务端可为空)
 	connectHostFunc ConnectHostFunc // 获取对应频道的一个连接地址
@@ -113,8 +114,8 @@ func (h *Hub) cleanDeadConnect() {
 
 // 获取通讯消息ID号
 func (h *Hub) GetID() uint16 {
-	h.Lock()
-	defer h.Unlock()
+	h.idMutex.Lock()
+	defer h.idMutex.Unlock()
 	h.globalID++
 	if h.globalID <= 0 || h.globalID >= config.ID_MAX {
 		h.globalID = 1
@@ -663,6 +664,8 @@ func (h *Hub) BindForServer(info *HostInfo) (err error) {
 // 新建一个连接,不同的连接协议由底层自己选择
 // channel: 要连接的频道信息,需要能表达频道关键信息的部分
 func (h *Hub) ConnectToServer(channel string, force bool, host *HostInfo, autoReconnect bool) (err error) {
+	h.connectMutex.Lock()
+	defer h.connectMutex.Unlock()
 	// 检查当前channel是否已经存在
 	if !force {
 		line := h.ChannelToLine(channel)

+ 1 - 1
line.go

@@ -322,9 +322,9 @@ func (c *Line) Start(channel string, conn conn.Connect, host *HostInfo) {
 	c.channel = channel
 	c.conn = conn
 	c.host = host
+	c.state = Connected
 	go c.readPump()
 	go c.writePump()
-	c.state = Connected
 	c.hub.connectStatusFunc(c)
 }