internal/transport: skip log on EOF when reading client preface (#4458)

This commit is contained in:
Easwar Swaminathan 2021-06-02 16:47:35 -07:00 committed by GitHub
parent e7b12ef3b1
commit 174b1c28af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 28 additions and 16 deletions

View File

@ -160,7 +160,7 @@ func (s *server) start(t *testing.T, port int, maxStreams uint32) {
config := &transport.ServerConfig{ config := &transport.ServerConfig{
MaxStreams: maxStreams, MaxStreams: maxStreams,
} }
st, err := transport.NewServerTransport("http2", conn, config) st, err := transport.NewServerTransport(conn, config)
if err != nil { if err != nil {
continue continue
} }

View File

@ -125,9 +125,14 @@ type http2Server struct {
connectionID uint64 connectionID uint64
} }
// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is // NewServerTransport creates a http2 transport with conn and configuration
// returned if something goes wrong. // options from config.
func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) { //
// It returns a non-nil transport and a nil error on success. On failure, it
// returns a non-nil transport and a nil-error. For a special case where the
// underlying conn gets closed before the client preface could be read, it
// returns a nil transport and a nil error.
func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
writeBufSize := config.WriteBufferSize writeBufSize := config.WriteBufferSize
readBufSize := config.ReadBufferSize readBufSize := config.ReadBufferSize
maxHeaderListSize := defaultServerMaxHeaderListSize maxHeaderListSize := defaultServerMaxHeaderListSize
@ -266,6 +271,13 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err
// Check the validity of client preface. // Check the validity of client preface.
preface := make([]byte, len(clientPreface)) preface := make([]byte, len(clientPreface))
if _, err := io.ReadFull(t.conn, preface); err != nil { if _, err := io.ReadFull(t.conn, preface); err != nil {
// In deployments where a gRPC server runs behind a cloud load balancer
// which performs regular TCP level health checks, the connection is
// closed immediately by the latter. Skipping the error here will help
// reduce log clutter.
if err == io.EOF {
return nil, nil
}
return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
} }
if !bytes.Equal(preface, clientPreface) { if !bytes.Equal(preface, clientPreface) {

View File

@ -532,12 +532,6 @@ type ServerConfig struct {
HeaderTableSize *uint32 HeaderTableSize *uint32
} }
// NewServerTransport creates a ServerTransport with conn or non-nil error
// if it fails.
func NewServerTransport(protocol string, conn net.Conn, config *ServerConfig) (ServerTransport, error) {
return newHTTP2Server(conn, config)
}
// ConnectOptions covers all relevant options for communicating with the server. // ConnectOptions covers all relevant options for communicating with the server.
type ConnectOptions struct { type ConnectOptions struct {
// UserAgent is the application user agent. // UserAgent is the application user agent.

View File

@ -323,7 +323,7 @@ func (s *server) start(t *testing.T, port int, serverConfig *ServerConfig, ht hT
if err != nil { if err != nil {
return return
} }
transport, err := NewServerTransport("http2", conn, serverConfig) transport, err := NewServerTransport(conn, serverConfig)
if err != nil { if err != nil {
return return
} }

View File

@ -844,10 +844,16 @@ func (s *Server) handleRawConn(lisAddr string, rawConn net.Conn) {
// ErrConnDispatched means that the connection was dispatched away from // ErrConnDispatched means that the connection was dispatched away from
// gRPC; those connections should be left open. // gRPC; those connections should be left open.
if err != credentials.ErrConnDispatched { if err != credentials.ErrConnDispatched {
// In deployments where a gRPC server runs behind a cloud load
// balancer which performs regular TCP level health checks, the
// connection is closed immediately by the latter. Skipping the
// error here will help reduce log clutter.
if err != io.EOF {
s.mu.Lock() s.mu.Lock()
s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err)
s.mu.Unlock() s.mu.Unlock()
channelz.Warningf(logger, s.channelzID, "grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err) channelz.Warningf(logger, s.channelzID, "grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err)
}
rawConn.Close() rawConn.Close()
} }
rawConn.SetDeadline(time.Time{}) rawConn.SetDeadline(time.Time{})
@ -897,7 +903,7 @@ func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) tr
MaxHeaderListSize: s.opts.maxHeaderListSize, MaxHeaderListSize: s.opts.maxHeaderListSize,
HeaderTableSize: s.opts.headerTableSize, HeaderTableSize: s.opts.headerTableSize,
} }
st, err := transport.NewServerTransport("http2", c, config) st, err := transport.NewServerTransport(c, config)
if err != nil { if err != nil {
s.mu.Lock() s.mu.Lock()
s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err) s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err)