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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user