mercari/gaurun

http2 error

Closed this issue · 6 comments

Hi,

I am receiving error for http2 transport. I know it probably is golang issue but how can I force a reconnect when this occurs?

Here is my logs:

2019/09/15 18:19:56 http2: Transport closing idle conn 0xc00034c000 (forSingleUse=false, maxStream=1)
2019/09/15 18:19:56 http2: Transport readFrame error on conn 0xc00034c000: (*net.OpError) read tcp 172.31.21.125:40224->17.188.138.73:443: use of closed network connection
2019/09/15 18:24:02 http2: Transport failed to get client conn for api.development.push.apple.com:443: http2: no cached connection was available
2019/09/15 18:24:02 http2: Transport failed to get client conn for api.development.push.apple.com:443: http2: no cached connection was available

My golang version is 1.13 and I'm using latest version of gaurun.

I managed to do a reconnect by modifying worker.go

func isExternalServerError(err error, platform int) bool {
	switch platform {
	case PlatFormIos:
		if err == push.ErrIdleTimeout || err == push.ErrShutdown || err == push.ErrInternalServerError || err == push.ErrServiceUnavailable || strings.Contains(err.Error(), "no cached connection") {
			InitAPNSClient()
			return true
		}
	case PlatFormAndroid:
		if err.Error() == "Unavailable" || err.Error() == "InternalServerError" || strings.Contains(err.Error(), "Timeout") || strings.Contains(err.Error(), "no cached connection") {
			InitGCMClient()
			return true
		}
	default:
		// not through
	}
	return false
}

However, this still does not solve the issue on why I'm getting readFrame error.

We also reproduce it on Go 1.13.

The step to reproduce the issue is the following:

  1. Send a push message to APNs
  2. Wait for ios.keepalive_timeout seconds
  3. Send a push message to APNS again

Then we can see "http2: no cached connection was available".

We can see the issue only on Go 1.13. I think that occurs on a compatible problem with golang.org/x/net/http2 package and Go 1.13.

Both http2.Tranport and http.Tranport have a connection pool.
https://github.com/golang/net/blob/4971afdc2f16/http2/transport.go#L71
https://github.com/golang/go/blob/28e8a0c21e00896f6da4cb0a8ad31e23daf18fff/src/net/http/transport.go#L98

For Go 1.12, http.Tranport does not keep a connection on its connection pool.

Since Go 1.13, both Tranports keep a connection to APNs. The http2.Tranport deletes the connection after ios.keepalive_timeout seconds, but http.Tranport does not.
Then Tranport.RoundTrip() called by client expect that the connection is available, but http2.Tranport returns ErrNoCachedConn.

Go 1.13 stores the connection into the pool after created.
https://github.com/golang/go/blob/dev.boringcrypto.go1.13/src/net/http/transport.go#L1303-L1306

I'm not very familiar with Go's internal and http2 implementation, but is it a bug on Go 1.13?

I tried to reproduce with latest golang.org/x/net/http2, but cannot. That may be fixed in current version.

I released version 0.12.0. This release includes #130. This should not happen.