Skip to content

HTTP/2 protocol lacks stream control, leading to REFUSED_STREAM errors when concurrency is high. #2412

@zhengjianglong915

Description

@zhengjianglong915

Describe the bug

My gateway is based on MOSN. I found a problem: MOSN reports REFUSED_STREAM in HTTP/2 protocol when concurrency is high. In HTTP/2 protocol, SETTING_MAX_CONCURRENT_STREAMS is used to control the maximum number of streams per client connection. However, I found that MOSN does not use the server's SETTING_MAX_CONCURRENT_STREAMS configuration. As a result, the client can send unlimited streams. This will result in REFUSED_STREAM being reported when the stream count exceeds the server's SETTING_MAX_CONCURRENT_STREAMS.

Minimal yet complete reproducer code (or GitHub URL to code)

mosn code:

func (cc *MClientStream) RoundTrip(ctx context.Context) (err error) {
	if !cc.sendHeader {
		cc.sendHeader = true
		//write header
		if cl, ok := cc.Request.Header["Content-Length"]; ok {
			cc.Request.ContentLength, _ = strconv.ParseInt(cl[0], 10, 64)
		}

		endStream := cc.SendData == nil && cc.Trailer == nil

		//if WriteHeader err
		cs, err := cc.conn.WriteHeaders(ctx, cc.Request, "", endStream)
		if err != nil {
			return err
		}
		cc.clientStream = cs

		return err
	}

	// write data and trailer
	endStream := cc.SendData == nil && cc.Trailer == nil
	if endStream {
		return
	}

	if !cc.UseStream {
		if err = cc.writeDataAndTrailer(); err != nil {
			cc.conn.HandleError(nil, cc.ID, err, cc.SendData)
		}
	} else {
		utils.GoWithRecover(func() {
			if err = cc.writeDataAndTrailer(); err != nil {
				cc.conn.HandleError(nil, cc.ID, err, cc.SendData)
			}
		}, nil)
	}
	return
}

http2 transport code:

func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
	....

	cc.mu.Lock()
        // control the stream 
	if err := cc.awaitOpenSlotForRequest(req); err != nil {
		cc.mu.Unlock()
		return nil, false, err
	}

	body := req.Body
	contentLen := actualContentLength(req)
	hasBody := contentLen != 0
      
        ....
}

Environment

  • MOSN Version: all version, you can see laster version.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions