feat(transport): 完成安全架构拆分并收口 stream/bulk 传输优化

- 新增 managed/external/nested 三种传输保护模式
  - 新增 peer attach 显式认证、抗重放、channel binding 和可选前向保密协商
  - 明确单连接注入与可重拨连接源的语义边界
  - 禁止 ConnectByConn 场景下 dedicated bulk 走 sidecar,auto 模式自动回退 shared
  - 修正 dedicated attach 在 bootstrap/steady profile 切换下的处理逻辑
  - 优化 shared bulk super-batch 与批量 framed write 路径
  - 降低 stream/bulk fast path 的复制和分发损耗
  - 补齐 benchmark、回归测试、运行时快照和 README 文档
This commit is contained in:
2026-04-20 16:35:44 +08:00
parent f038a89771
commit 98ef9e7fcc
52 changed files with 4069 additions and 445 deletions
+90 -14
View File
@@ -89,6 +89,60 @@ type streamCloseSender func(context.Context, *streamHandle, bool) error
type streamResetSender func(context.Context, *streamHandle, string) error
type streamDataSender func(context.Context, *streamHandle, []byte) error
type streamReadChunk struct {
data []byte
release func()
}
func (c *streamReadChunk) clear() {
if c == nil {
return
}
if c.release != nil {
c.release()
}
c.data = nil
c.release = nil
}
type streamReadPayloadOwner struct {
refs atomic.Int32
release func()
}
func newStreamReadPayloadOwner(release func()) *streamReadPayloadOwner {
if release == nil {
return nil
}
owner := &streamReadPayloadOwner{release: release}
owner.refs.Store(1)
return owner
}
func (o *streamReadPayloadOwner) retainChunk() func() {
if o == nil {
return nil
}
o.refs.Add(1)
return o.releaseChunk
}
func (o *streamReadPayloadOwner) releaseChunk() {
if o == nil {
return
}
if o.refs.Add(-1) == 0 && o.release != nil {
o.release()
}
}
func (o *streamReadPayloadOwner) done() {
if o == nil {
return
}
o.releaseChunk()
}
type streamHandle struct {
runtime *streamRuntime
runtimeScope string
@@ -124,8 +178,8 @@ type streamHandle struct {
remoteClosed bool
peerReadClosed bool
resetErr error
readQueue [][]byte
readBuf []byte
readQueue []streamReadChunk
readBuf streamReadChunk
bufferedBytes int
readNotify chan struct{}
readDeadline time.Time
@@ -339,20 +393,23 @@ func (s *streamHandle) Read(p []byte) (int, error) {
for {
s.mu.Lock()
localReadClosed := s.localReadClosed
if len(s.readBuf) > 0 {
n := copy(p, s.readBuf)
s.readBuf = s.readBuf[n:]
if len(s.readBuf.data) > 0 {
n := copy(p, s.readBuf.data)
s.readBuf.data = s.readBuf.data[n:]
s.bufferedBytes -= n
if s.bufferedBytes < 0 {
s.bufferedBytes = 0
}
if len(s.readBuf.data) == 0 {
s.readBuf.clear()
}
s.recordReadLocked(n, time.Now())
s.mu.Unlock()
return n, nil
}
if len(s.readQueue) > 0 {
s.readBuf = s.readQueue[0]
s.readQueue[0] = nil
s.readQueue[0] = streamReadChunk{}
s.readQueue = s.readQueue[1:]
s.mu.Unlock()
continue
@@ -824,43 +881,61 @@ func (s *streamHandle) pushOwnedChunk(chunk []byte) error {
return s.pushChunkWithOwnership(chunk, true)
}
func (s *streamHandle) pushOwnedChunkWithRelease(chunk []byte, release func()) error {
return s.pushChunkWithOwnershipAndRelease(chunk, true, release)
}
func (s *streamHandle) pushChunkWithOwnership(chunk []byte, owned bool) error {
return s.pushChunkWithOwnershipAndRelease(chunk, owned, nil)
}
func (s *streamHandle) pushChunkWithOwnershipAndRelease(chunk []byte, owned bool, release func()) error {
if s == nil {
return io.ErrClosedPipe
}
if len(chunk) == 0 {
if release != nil {
release()
}
return nil
}
stored := chunk
stored := streamReadChunk{data: chunk, release: release}
if !owned {
stored = append([]byte(nil), chunk...)
stored.data = append([]byte(nil), chunk...)
if stored.release != nil {
stored.release()
stored.release = nil
}
}
s.mu.Lock()
if s.resetErr != nil {
err := s.resetErr
s.mu.Unlock()
stored.clear()
return err
}
if s.inboundQueueLimit > 0 && s.bufferedChunkCountLocked() >= s.inboundQueueLimit {
err := s.markResetLocked(errStreamBackpressureExceeded)
s.mu.Unlock()
stored.clear()
s.notifyReadable()
s.finalize()
return err
}
if s.inboundBytesLimit > 0 && s.bufferedBytes+len(stored) > s.inboundBytesLimit {
if s.inboundBytesLimit > 0 && s.bufferedBytes+len(stored.data) > s.inboundBytesLimit {
err := s.markResetLocked(errStreamBackpressureExceeded)
s.mu.Unlock()
stored.clear()
s.notifyReadable()
s.finalize()
return err
}
if len(s.readBuf) == 0 && len(s.readQueue) == 0 {
if len(s.readBuf.data) == 0 && len(s.readQueue) == 0 {
s.readBuf = stored
} else {
s.readQueue = append(s.readQueue, stored)
}
s.bufferedBytes += len(stored)
s.bufferedBytes += len(stored.data)
s.notifyReadableLocked()
s.mu.Unlock()
return nil
@@ -881,11 +956,12 @@ func (s *streamHandle) clearBufferedDataLocked() {
if s == nil {
return
}
s.readBuf.clear()
for i := range s.readQueue {
s.readQueue[i] = nil
s.readQueue[i].clear()
}
s.readQueue = nil
s.readBuf = nil
s.readBuf = streamReadChunk{}
s.bufferedBytes = 0
}
@@ -894,7 +970,7 @@ func (s *streamHandle) bufferedChunkCountLocked() int {
return 0
}
count := len(s.readQueue)
if len(s.readBuf) > 0 {
if len(s.readBuf.data) > 0 {
count++
}
return count