fix(notify): 修复传输生命周期竞态,完善背压与协议边界
- 完善 stream/bulk DataID 分配、预留和双向命名空间,修复并发打开及 dedicated/shared 回退时的 ID 冲突 - 将收发、回复、恢复任务和 sidecar 绑定原始会话与物理连接,防止重连后的旧消息误操作新连接 - 加强 close/reset 身份校验及实例移除检查,修复 dedicated attach 失败、通道引用和资源回收竞态 - 收紧批量发送器停止准入,确保在途入队完成后统一清理请求、缓冲区和等待者 - 修复 record 满队列死锁、取消时序号消耗及关闭竞态,确保关闭有界并返回真实错误 - 增加协商式 record 逻辑半关闭,保留反向 ACK;通过 reset 传递 RecordFailure,避免背压掩盖原始失败原因 - 补齐帧长度、批次数量、序号溢出和未确认窗口校验,提前拒绝超限数据并按字节预算拆批 - 为入站分发增加全局及单连接的条数、字节预算和阻塞背压,关闭时唤醒等待者,消除正常断连日志噪音 - 完善 bulk 窗口释放失败处理与传输诊断,补充并发、重连、背压、协议边界及真实 TCP 回归覆盖
This commit is contained in:
+26
-8
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -286,7 +285,7 @@ func (c *ClientCommon) startClientWithConn(conn net.Conn) error {
|
||||
func (c *ClientCommon) startClientWithConnSource(conn net.Conn, source *clientConnectSource) error {
|
||||
stopCtx, stopFn := context.WithCancel(context.Background())
|
||||
epoch := c.beginClientSessionEpoch()
|
||||
queue := stario.NewQueueCtx(stopCtx, 4, math.MaxUint32)
|
||||
queue := stario.NewQueueCtx(stopCtx, 4, transportFrameMaxPayloadBytes)
|
||||
c.setClientConnectSource(source)
|
||||
rt := newClientSessionRuntime(conn, stopCtx, stopFn, queue, epoch)
|
||||
c.setClientSessionRuntimeWithCloseOld(rt, true)
|
||||
@@ -341,7 +340,7 @@ func (c *ClientCommon) startClientTransportRuntime(rt *clientSessionRuntime) err
|
||||
if c.useHeartBeat {
|
||||
go c.heartbeatLoop(transportStopCtx, rt.epoch)
|
||||
}
|
||||
go c.readMessageLoop(transportStopCtx, rt.conn, rt.queue, rt.epoch)
|
||||
go c.readMessageLoopAtRoute(transportStopCtx, clientSessionRouteFromRuntime(rt))
|
||||
go c.loadMessageLoop(rt)
|
||||
return nil
|
||||
}
|
||||
@@ -440,10 +439,28 @@ func (c *ClientCommon) readMessage() {
|
||||
}
|
||||
|
||||
func (c *ClientCommon) readMessageLoop(stopCtx context.Context, conn net.Conn, queue *stario.StarQueue, epoch uint64) {
|
||||
route := c.clientSessionRouteSnapshot()
|
||||
if route.binding == nil || route.binding.connSnapshot() != conn || route.binding.queueSnapshot() != queue || route.epoch != epoch {
|
||||
route = clientSessionRoute{
|
||||
binding: newTransportBinding(conn, queue),
|
||||
epoch: epoch,
|
||||
sessionStopCtx: stopCtx,
|
||||
transportStopCtx: stopCtx,
|
||||
}
|
||||
}
|
||||
c.readMessageLoopAtRoute(stopCtx, route)
|
||||
}
|
||||
|
||||
func (c *ClientCommon) readMessageLoopAtRoute(stopCtx context.Context, route clientSessionRoute) {
|
||||
if stopCtx == nil {
|
||||
return
|
||||
}
|
||||
binding := newTransportBinding(conn, queue)
|
||||
binding := route.binding
|
||||
if binding == nil {
|
||||
return
|
||||
}
|
||||
conn := binding.connSnapshot()
|
||||
queue := binding.queueSnapshot()
|
||||
dispatcher := c.clientInboundDispatcherSnapshot()
|
||||
if conn != nil && queue != nil && !isPacketTransportConn(conn) {
|
||||
reader := newTransportFrameReader(conn, queue)
|
||||
@@ -455,7 +472,7 @@ func (c *ClientCommon) readMessageLoop(stopCtx context.Context, conn net.Conn, q
|
||||
default:
|
||||
}
|
||||
payload, release, err := c.readTransportPayloadPooled(conn, reader)
|
||||
if !c.handleTransportPayloadReadResultWithSession(stopCtx, binding, payload, release, err, epoch, dispatcher) {
|
||||
if !c.handleTransportPayloadReadResultAtRoute(stopCtx, route, payload, release, err, dispatcher) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -469,7 +486,7 @@ func (c *ClientCommon) readMessageLoop(stopCtx context.Context, conn net.Conn, q
|
||||
default:
|
||||
}
|
||||
readNum, data, err := c.readFromTransportBindingWithBuffer(binding, buf)
|
||||
if !c.handleTransportReadResultWithSessionDispatcher(stopCtx, conn, queue, readNum, data, err, epoch, dispatcher) {
|
||||
if !c.handleTransportReadResultAtRoute(stopCtx, route, readNum, data, err, dispatcher) {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -512,6 +529,7 @@ func (c *ClientCommon) loadMessageLoop(rt *clientSessionRuntime) {
|
||||
return
|
||||
}
|
||||
dispatcher := rt.inboundDispatcher
|
||||
route := clientSessionRouteFromRuntime(rt)
|
||||
if dispatcher == nil {
|
||||
dispatcher = newInboundDispatcher()
|
||||
defer dispatcher.CloseAndWait()
|
||||
@@ -534,10 +552,10 @@ func (c *ClientCommon) loadMessageLoop(rt *clientSessionRuntime) {
|
||||
}
|
||||
msg := data
|
||||
c.wg.Add(1)
|
||||
if !dispatcher.Dispatch(clientInboundDispatchSource(), func() {
|
||||
if !dispatcher.DispatchSized(clientInboundDispatchSource(), len(msg.Msg), func() {
|
||||
defer c.wg.Done()
|
||||
now := time.Now()
|
||||
if err := c.dispatchInboundTransportPayload(msg.Msg, now); err != nil {
|
||||
if err := c.dispatchInboundTransportPayloadAtRoute(route, msg.Msg, now); err != nil {
|
||||
if c.showError || c.debugMode {
|
||||
fmt.Println("client decode envelope error", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user