grpc一次请求的流程图
![](https://github.com/forcht/go-example/blob/master/grpc/image/gRPC%E4%B8%80%E6%AC%A1%E8%AF%B7%E6%B1%82%E6%B5%81%E7%A8%8B%E5%9B%BE.jpg?raw=true)
下面详细介绍每个过程
- 1.启动服务,监听端口,接收客户端建立连接的请求
func (s *Server) Serve(lis net.Listener) error {
//加锁
s.mu.Lock()
s.printf("serving")
//标记服务已经启动
s.serve = true
//如果服务监听列表为空,说明服务已经被关闭过,因为服务关闭时会将服务监听的列表置空
if s.lis == nil {
//释放锁
s.mu.Unlock()
//关闭监听器
lis.Close()
return ErrServerStopped
}
//
s.serveWG.Add(1)
defer func() {
s.serveWG.Done()
select {
// Stop or GracefulStop called; block until done and return nil.
//如果quit返回,说明quit已经关闭,服务正在关闭中,需要等待done关闭才能退出服务
case <-s.quit:
<-s.done
default:
}
}()
//TODO 创建 并保存监听器
ls := &listenSocket{
Listener: lis}
s.lis[ls] = true
//TODO
if channelz.IsOn() {
ls.channelzID = channelz.RegisterListenSocket(ls, s.channelzID, lis.Addr().String())
}
//释放锁
s.mu.Unlock()
defer func() {
//加锁
s.mu.Lock()
//关闭监听器,并把监听器从监听列表移除
if s.lis != nil && s.lis[ls] {
ls.Close()
delete(s.lis, ls)
}
//释放锁
s.mu.Unlock()
}()
var tempDelay time.Duration // how long to sleep on accept failure
for {
//监听到请求
rawConn, err := lis.Accept()
if err != nil {
//判断err是否实现了temporary,如果实现了则是临时错误,可以尝试重试
if ne, ok := err.(interface {
Temporary() bool
}); ok && ne.Temporary() {
//先尝试5ms后重试,再次失败后按之前的两倍时间重试
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
//重试停顿时间不能超过一秒
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
s.mu.Lock()
s.printf("Accept error: %v; retrying in %v", err, tempDelay)
s.mu.Unlock()
//创建定时器
timer := time.NewTimer(tempDelay)
//等待定时器返回或者quit返回
select {
case <-timer.C:
case <-s.quit:
timer.Stop()
return nil
}
continue
}
//如果不是临时错误则等待quit返回
s.mu.Lock()
s.printf("done serving; Accept = %v", err)
s.mu.Unlock()
select {
case <-s.quit:
return nil
default:
}
return err
}
//有正常连接后将tempDelay置0
tempDelay = 0
s.serveWG.Add(1)
//开启一个goroutine处理请求
go func() {
s.handleRawConn(rawConn)
s.serveWG.Done()
}()
}
}
- 2.处理客户端建立连接的请求
func (s *Server) handleRawConn(rawConn net.Conn) {
//设置读写超时时间
rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout))
//验证握手,返回加密连接
conn, authInfo, err := s.useTransportAuthenticator(rawConn)
if err != nil {
s.mu.Lock()
s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err)
s.mu.Unlock()
grpclog.Warningf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err)
// If serverHandshake returns ErrConnDispatched, keep rawConn open.
if err != credentials.ErrConnDispatched {
rawConn.Close()
}
rawConn.SetDeadline(time.Time{
})
return
}
s.mu.Lock()
//如果监听器集为nil,说明服务器已经关闭,则直接关闭连接
if s.conns == nil {
s.mu.Unlock()
conn.Close()
return
}
s.mu.Unlock()
// Finish handshaking (HTTP2)
//完成握手,建立HTTP2.0的连接
st := s.newHTTP2Transport(conn, authInfo)