go-grpc核心抽象接口

ClientConnInterface接口:

1.定义位置:

clientconn.go:645-651

2.具体作用:

只抽象"发起 RPC"的最小能力:一元调用(Invoke)+ 建流(NewStream).

3. 实现类:

ClientConn类(clientconn.go:668):

*acBalancerWrapper(balancer_wrapper.go:361,372):

balancer接口:

1.定义位置:

balancer/balancer.go:344

UpdateClientConnState:

最核心的入口。resolver 每次解析出新地址列表/服务配置,gRPC 就带着 ClientConnState{ResolverState, BalancerConfig} 调它。balancer 在这里 diff 新旧地址 → NewSubConn/Shutdown 多余的子连接。返回 ErrBadResolverState 会触发 gRPC 带指数退避地重试 ResolveNow(balancer.go:345-349),这是 balancer 反向影响 resolver 的唯一通道。

ResolverError:

解析失败的通知,balancer 通常把聚合状态置为 TransientFailure 并换上一个报错 Picker。

UpdateSubConnState:

某个子连接 CONNECTING/READY/TRANSIENT_FAILURE 时回调。已废弃------现在推荐建 SubConn 时通过 NewSubConnOptions.StateListener 注册回调(balancer.go:356-357),新策略都用 StateListener。

Close:

销毁前释放资源(未来会强制要求把所有 SubConn Shutdown)。

ExitIdle:

idle 模式被唤醒时,让策略主动发起重连(调 SubConn.Connect)。

2.具体作用:

接收 gRPC 的输入(地址、连接状态),管理 SubConn,聚合连接状态,生成并更新 Picker.

3. 实现类:

pickfirstBalancer(balancer/pickfirst/pickfirst.go:210):

默认策略。不用 base,面向单个SubConn顺序试连第一个可用地址

rrBalancer(balancer/roundrobin/roundrobin.go:66):

轮询,基于 base,自己只有 ~30 行Picker.

ringhashBalancer(balancer/ringhash/ringancer.go:181→ringhash.go:181):

一致性哈希环(xDS 用).

leastRequestBalancer(balancer/leastrequest/leastrequest.go:131):

最少请求数(借助 ORCA 负载上报).

wrrBalancer(balancer/weightedroundrobin/balancer.go:224):

加权轮询.

weightedTargetBalancer(balancer/weightedtarget/weightedtarget.go:100):

按权重分组再下发子策略.

lbBalancer(balancer/grpclb/grpclb.go:465):

老的 gRPC LB 协议(客户端连 LB server 拿地址).

rlsBalancer(balancer/grpclb/grpclb.go:465):

路由查找服务:按 key 查 RLSserver 决定路由到哪.

Resolver接口:

1.定义位置:

resolver/resolver.go:319-327

2.具体作用:

ResolveNow:

gRPC 主动要求重解析的提示通道。典型触发:balancer 发现地址全连不上、返回 ErrBadResolverState,ClientConn 就带指数退避地反复调它------它是 balancer → resolver 的反馈回路,让解析器知道"你给的结果不可用,刷新一下"。声明为"可忽略"是给 watch 型 resolver(xDS)留的余地:人家本来就是推送模式,没有"再查一次"的概念。

Close:

与 ClientConn 同生共死,释放 DNS goroutine、取消订阅、断开 xDS stream。

3. 实现类:

passthroughResolver(internal/resolver/passthrough/passthrough.go:49):

最"懒"的 resolver:Build 时把 target 原样当作地址 UpdateState(passthrough.go:55),ResolveNow 空实现(:58)。IP

直连场景用,老 Dial("localhost:50051") 背后就是它.

dnsResolver( internal/resolver/dns/dns_resolver.go:193):

真解析:A/AAAA 记录、SRV 记录(_grpclb._tcp)、TXT 里的服务配置;带结果缓存、退避重试。NewClient 无 scheme 时的默认.

delegatingResolver(internal/resolver/delegatingresolver/delegatingresolver.go:184):

新的组合壳:target 里的裸 IP 交给 passthrough、主机名交给 dns,并处理双栈 Endpoint 聚合------未来默认 resolver 的方向.

xdsResolver(internal/xds/resolver/xds_resolver.go:276):

从 xDS 管理面订阅 LDS/RDS,输出的是"该用哪个 LB 策略 + 集群配置",而非简单地址列表.

manual.Resolver(resolver/manual/manual.go:98):

测试专用:手动 UpdateState() 注入任意 State,grpc-go 自己的测试大量使用.

Transport 接口

1.定义位置:

internal/transport/transport.go,两个接口,分别管客户端和服务端:

ClientTransport ------ transport.go:714,7 个方法

Go 复制代码
type ClientTransport interface {
	// Close tears down this transport. Once it returns, the transport
	// should not be accessed any more. The caller must make sure this
	// is called only once.
	Close(err error)

	// GracefulClose starts to tear down the transport: the transport will stop
	// accepting new RPCs and NewStream will return error. Once all streams are
	// finished, the transport will close.
	//
	// It does not block.
	GracefulClose()

	// NewStream creates a Stream for an RPC.
	NewStream(ctx context.Context, callHdr *CallHdr, handler stats.Handler) (*ClientStream, error)

	// Error returns a channel that is closed when some I/O error
	// happens. Typically the caller should have a goroutine to monitor
	// this in order to take action (e.g., close the current transport
	// and create a new one) in error case. It should not return nil
	// once the transport is initiated.
	Error() <-chan struct{}

	// GoAway returns a channel that is closed when ClientTransport
	// receives the draining signal from the server (e.g., GOAWAY frame in
	// HTTP/2).
	GoAway() <-chan struct{}

	// GetGoAwayReason returns the reason why GoAway frame was received, along
	// with a human readable string with debug info.
	GetGoAwayReason() (GoAwayReason, string)

	// Peer returns information about the peer associated with the Transport.
	// The returned information includes authentication and network address details.
	Peer() *peer.Peer
}

开流:NewStream 是数据面的真正入口------把 CallHdr(method、:authority、压缩、credentials,transport.go:670-710)变成一个 HTTP/2 stream。之前讲的 acBalancerWrapper.NewStream 最终就落到这。

关闭语义:暴力 Close vs 优雅 GracefulClose,后者对应连接排水的方向;

健康信号:Error()/GoAway() 两个 channel 是 transport → ClientConn 的反馈通道:addrConn 里有 goroutine 监听它们------Error 触发重连(退避),GoAway 触发重新解析 + 连接迁移(服务端要下线时提前通知,客户端去连新的后端,在途请求不受影响------这就是 gRPC 优雅重启的底层机制);

元信息:Peer() 给 stats/tracing 用。

ServerTransport ------ transport.go:756,4 个方法

HandleStreams:

读循环:每收到一个新流,回调给 Server 分发.

Close:

拆连接,在途流异步终止.

Drain:

给客户端发 GOAWAY:别再发新请求.

Peer:

对端信息快照.

2.具体作用:

3. 实现类:

现http2Client(internal/transport/http2_client.go(NewStream:778,Close:1028...):

唯一的客户端实现。自管 TCP/TLS 拨号、framer、读循环 + loopyWriter 写循环(专门的发帧 goroutine,攒批写),还负责

HTTP/2 SETTINGS MAX_CONCURRENT_STREAMS 限流(NewStream 时可能排队/失败)

http2Server(internal/transport/http2_server.go(HandleStreams:646,Drain:1394):

服务端主力:accept 后的 HTTP/2 连接.

serverHandlerTransport(internal/transport/handler_server.go:145):

备用服务端实现:不走自己的 HTTP/2,而是架在 Go 标准库 http.Server 的 Handler 上(h2c)。场景:gRPC 和普通 HTTP 共用

443 端口(如 cmux、ServeMux 一端口多协议).

客户端只有 http2Client 一个实现,却仍抽接口------为将来换传输实现(in-process、quic 等)留缝,也为了让 addrConn/csAttempt 依赖抽象而非具体类型。

相关推荐
kimnoic1 小时前
Python操作Git命令的详细指南
开发语言·python
FYKJ_20101 小时前
django个性化新闻推荐35173-计算机课程设计、毕业设计
java·spring boot·后端·python·架构·django·课程设计
kimnoic1 小时前
Python数据库sqlite3图文实例详解
开发语言·python
小小龙学IT1 小时前
etcd 深度解析:Go 分布式一致性 KV 存储与 Raft 共识实战
分布式·golang·etcd
谢亮_vipxieliang1 小时前
Go Gin 中间件与参数验证:从入门到实战
中间件·golang·gin
夜之眷属1 小时前
服务启动即崩:InetAddress.getLocalHost() 抛 UnknownHostException 排查记
java·运维·后端·docker
老王爱玩车2 小时前
文件操作从打开到缓冲区
c语言·开发语言·学习
SunnyDays10112 小时前
Java 合并 PDF 文件:完整合并、指定页面合并与流合并
java·开发语言·合并pdf