http2 icon indicating copy to clipboard operation
http2 copied to clipboard

fasthttp http2 Whether connection-level health probes are supported

Open zxpdmw opened this issue 1 year ago • 13 comments

zxpdmw avatar Sep 26 '23 06:09 zxpdmw

image What this does is simulate a network/http2 connection-level health probe

zxpdmw avatar Sep 26 '23 06:09 zxpdmw

Hello, as far as I remember the client does ping the server using the PingInterval, but it doesn't close the connection if a number of pings failed. I'd accept a PR for that. https://github.com/dgrr/http2/blob/master/conn.go#L459

dgrr avatar Sep 26 '23 09:09 dgrr

Why only fasthttp.hostclient support http2

zxpdmw avatar Sep 27 '23 07:09 zxpdmw

If the client fails to ping the server for many times, it hopes to close the connection in time, so that the request fails quickly and enters the retry logic

zxpdmw avatar Sep 27 '23 07:09 zxpdmw

func (c *Conn) writeLoop() {
	var lastErr error

	defer func() { _ = c.Close() }()

	defer func() {
		if err := recover(); err != nil {
			if lastErr == nil {
				switch errn := err.(type) {
				case error:
					lastErr = errn
				case string:
					lastErr = errors.New(errn)
				}
			}
		}

		if lastErr == nil {
			lastErr = io.ErrUnexpectedEOF
		}

		c.reqQueued.Range(func(_, v interface{}) bool {
			r := v.(*Ctx)
			r.resolve(lastErr)

			return true
		})
	}()

	if c.pingInterval <= 0 {
		c.pingInterval = DefaultPingInterval
	}

	ticker := time.NewTicker(c.pingInterval)
	defer ticker.Stop()

loop:
	for {
		select {
		case ctx, ok := <-c.in: // sending requests
			if !ok {
				break loop
			}

			err := c.writeRequest(ctx)
			if err != nil {
				ctx.resolve(err)

				if errors.Is(err, ErrNotAvailableStreams) {
					continue
				}

				lastErr = WriteError{err}

				break loop
			}
		case fr, ok := <-c.out: // generic output
			if !ok {
				break loop
			}

			err := c.writeFrame(fr)
			if err != nil {
				lastErr = WriteError{err}
				break loop
			}

			ReleaseFrameHeader(fr)
		case <-ticker.C: // ping
			if err := c.writePing(); err != nil {
				lastErr = WriteError{err}
				break loop
			}
		}

		if !c.disableAcks && c.unacks >= 3 {
			lastErr = ErrTimeout
			break loop
		}
	}
}

defer c.Close Won't the connection be closed

		if !c.disableAcks && c.unacks >= 3 {
			lastErr = ErrTimeout
			break loop
		}

If ack is enabled and the number of acks is greater than three times, it will jump out of the loop, and eventually it will execute until the defer closes the connection

zxpdmw avatar Sep 27 '23 07:09 zxpdmw

writeLoop AND readLoop The method is all the same logic

zxpdmw avatar Sep 27 '23 07:09 zxpdmw

Fasthttp HTTP2 Client looks like the code implementation has implemented connection-level health detection

zxpdmw avatar Sep 27 '23 07:09 zxpdmw

Yes, it seems like it. Is your question resolved?

dgrr avatar Sep 27 '23 08:09 dgrr

I use this library, it seems that I am still using http1, and the example in the code log does not run

zxpdmw avatar Sep 27 '23 08:09 zxpdmw

Does the server support HTTP/2? Are you connecting through TLS?

dgrr avatar Sep 27 '23 10:09 dgrr

Without using TLS, the example in my repository won't work in http2

zxpdmw avatar Oct 07 '23 01:10 zxpdmw

Yes, the library only supports TLS.

dgrr avatar Oct 07 '23 05:10 dgrr

Do the client and server support TLS at the same time?

zxpdmw avatar Oct 08 '23 01:10 zxpdmw