fix(notify): 根治低带宽控制面阻塞与传输写入卡死
- 为控制消息增加优先级、公平调度、队列字节预算和自适应批处理 - 支持可取消的写门等待,收紧 shared/dedicated bulk、stream 和 Reply 写入边界 - 修复 bulk reset/close、连接 handoff 和安全 profile 切换时序 - 保留旧取消与超时错误契约,新增阶段化 TransportSendError - 增加 ReplyCtx、ReplyObjCtx、写超时配置及黑洞连接和竞态回归测试
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
package notify
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const defaultMessageReplyWriteTimeout = 30 * time.Second
|
||||
|
||||
const (
|
||||
MSG_SYS MessageType = iota
|
||||
MSG_SYS_WAIT
|
||||
@@ -55,16 +58,40 @@ type WaitMsg struct {
|
||||
}
|
||||
|
||||
type messageLogicalTransferSender interface {
|
||||
sendLogical(*LogicalConn, TransferMsg) (WaitMsg, error)
|
||||
sendLogicalContext(context.Context, *LogicalConn, TransferMsg, time.Duration) (WaitMsg, error)
|
||||
}
|
||||
|
||||
type messageTransportTransferSender interface {
|
||||
sendTransportContextWithWriteTimeout(context.Context, *TransportConn, TransferMsg, time.Duration) (WaitMsg, error)
|
||||
}
|
||||
|
||||
type messageInboundTransferSender interface {
|
||||
sendTransferInbound(*LogicalConn, *TransportConn, net.Conn, *transportProtectionProfile, TransferMsg) error
|
||||
sendTransferInboundContext(context.Context, *LogicalConn, *TransportConn, net.Conn, *transportProtectionProfile, TransferMsg, time.Duration) error
|
||||
}
|
||||
|
||||
type messageClientTransferSender interface {
|
||||
sendWithContextTimeout(context.Context, TransferMsg, time.Duration) (WaitMsg, error)
|
||||
}
|
||||
|
||||
type messageReplyWriteTimeoutProvider interface {
|
||||
ReplyWriteTimeout() time.Duration
|
||||
}
|
||||
|
||||
func (m *Message) Reply(value MsgVal) (err error) {
|
||||
return m.replyContext(context.Background(), value)
|
||||
}
|
||||
|
||||
func (m *Message) ReplyCtx(ctx context.Context, value MsgVal) (err error) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
return m.replyContext(ctx, value)
|
||||
}
|
||||
|
||||
func (m *Message) replyContext(ctx context.Context, value MsgVal) (err error) {
|
||||
logical := messageLogicalConnSnapshot(m)
|
||||
transport := messageTransportConnSnapshot(m)
|
||||
writeTimeout := defaultMessageReplyWriteTimeout
|
||||
reply := TransferMsg{
|
||||
ID: m.ID,
|
||||
Key: m.Key,
|
||||
@@ -78,21 +105,6 @@ func (m *Message) Reply(value MsgVal) (err error) {
|
||||
reply.Type = MSG_SYS_REPLY
|
||||
}
|
||||
if m.NetType == NET_SERVER {
|
||||
if m.inboundConn != nil && logical != nil {
|
||||
server := logical.Server()
|
||||
if server == nil {
|
||||
return transportDetachedErrorForPeer(logical, transport)
|
||||
}
|
||||
sender, _ := server.(messageInboundTransferSender)
|
||||
if sender == nil {
|
||||
return transportDetachedErrorForPeer(logical, transport)
|
||||
}
|
||||
return sender.sendTransferInbound(logical, transport, m.inboundConn, messageInboundTransportProtectionSnapshot(m), reply)
|
||||
}
|
||||
if transport != nil {
|
||||
_, err = transport.sendTransfer(reply)
|
||||
return
|
||||
}
|
||||
if logical == nil {
|
||||
return transportDetachedErrorForPeer(nil, transport)
|
||||
}
|
||||
@@ -100,24 +112,53 @@ func (m *Message) Reply(value MsgVal) (err error) {
|
||||
if server == nil {
|
||||
return transportDetachedErrorForPeer(logical, transport)
|
||||
}
|
||||
if provider, ok := server.(messageReplyWriteTimeoutProvider); ok {
|
||||
writeTimeout = provider.ReplyWriteTimeout()
|
||||
}
|
||||
if m.inboundConn != nil && logical != nil {
|
||||
sender, _ := server.(messageInboundTransferSender)
|
||||
if sender == nil {
|
||||
return transportDetachedErrorForPeer(logical, transport)
|
||||
}
|
||||
return sender.sendTransferInboundContext(ctx, logical, transport, m.inboundConn, messageInboundTransportProtectionSnapshot(m), reply, writeTimeout)
|
||||
}
|
||||
if transport != nil {
|
||||
sender, _ := server.(messageTransportTransferSender)
|
||||
if sender == nil {
|
||||
return transportDetachedErrorForPeer(logical, transport)
|
||||
}
|
||||
_, err = sender.sendTransportContextWithWriteTimeout(ctx, transport, reply, writeTimeout)
|
||||
return err
|
||||
}
|
||||
sender, _ := server.(messageLogicalTransferSender)
|
||||
if sender == nil {
|
||||
return transportDetachedErrorForPeer(logical, transport)
|
||||
}
|
||||
_, err = sender.sendLogical(logical, reply)
|
||||
_, err = sender.sendLogicalContext(ctx, logical, reply, writeTimeout)
|
||||
}
|
||||
if m.NetType == NET_CLIENT {
|
||||
_, err = m.ServerConn.send(reply)
|
||||
if m.ServerConn == nil {
|
||||
return net.ErrClosed
|
||||
}
|
||||
if sender, ok := m.ServerConn.(messageClientTransferSender); ok {
|
||||
_, err = sender.sendWithContextTimeout(ctx, reply, writeTimeout)
|
||||
} else {
|
||||
_, err = m.ServerConn.send(reply)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *Message) ReplyObj(value interface{}) (err error) {
|
||||
return m.ReplyObjCtx(context.Background(), value)
|
||||
}
|
||||
|
||||
func (m *Message) ReplyObjCtx(ctx context.Context, value interface{}) (err error) {
|
||||
data, err := encode(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.Reply(data)
|
||||
return m.ReplyCtx(ctx, data)
|
||||
}
|
||||
|
||||
func hydrateServerMessagePeerFields(message Message) Message {
|
||||
|
||||
Reference in New Issue
Block a user