-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unexpected HTTP2 END_STREAM and keep alive behavior #113
Comments
I tried this same application with a custom virtual network. Adjusting the idle timeout on both the load balancer and external ip of the subnet had no effect on the timeout time (still 4 minutes). It seems the component that is timing out the connection is part of the kubernetes backend pool. I also verified that the gRPC server application also gets ping acks, but they are not coming from the gRPC client. Something is responding to http2 pings but not allowing them to pass through. |
Hi @RichardLaos, sorry for the delay. I wanted to try to repro this to see if it's the default timeout we set on idle connection or if something else is causing it. However, I'm not able to reproduce the issue. Serverpackage main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Received: %v", in.GetName())
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
} Clientimport (
"context"
"fmt"
"os"
"os/signal"
"runtime"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
"google.golang.org/grpc/keepalive"
)
func main() {
keepaliveParams := keepalive.ClientParameters{
Time: 5 * time.Second,
Timeout: 5 * time.Second,
PermitWithoutStream: true,
}
conn, err := grpc.Dial("greet-server.orangebeach-3169496f.eastus2.azurecontainerapps.io:80",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithKeepaliveParams(keepaliveParams))
if err != nil {
panic(err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
r, err := c.SayHello(context.TODO(), &pb.HelloRequest{Name: "Test"})
if err != nil {
panic(err)
}
fmt.Println(r.Message)
fmt.Printf("%+v", conn.GetState())
cc := make(chan os.Signal, 1)
signal.Notify(cc, os.Interrupt)
<-cc
} and I see pings going on for more than 4 minutes Client logs2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote SETTINGS len=0
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read SETTINGS len=0
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote SETTINGS flags=ACK len=0
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote HEADERS flags=END_HEADERS stream=1 len=112
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote DATA flags=END_STREAM stream=1 len=11 data="\x00\x00\x00\x00\x06\n\x04Test"
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read SETTINGS len=30, settings: HEADER_TABLE_SIZE=4096, MAX_CONCURRENT_STREAMS=100, INITIAL_WINDOW_SIZE=65536, MAX_FRAME_SIZE=16384, MAX_HEADER_LIST_SIZE=65535
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read WINDOW_UPDATE len=4 (conn) incr=2147418112
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read SETTINGS flags=ACK len=0
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote SETTINGS flags=ACK len=0
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read HEADERS flags=END_HEADERS stream=1 len=71
2022/03/03 17:36:28 http2: decoded hpack field header field ":status" = "200"
2022/03/03 17:36:28 http2: decoded hpack field header field "content-type" = "application/grpc" (sensitive)
2022/03/03 17:36:28 http2: decoded hpack field header field "date" = "Fri, 04 Mar 2022 01:36:29 GMT" (sensitive)
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read DATA stream=1 len=17 data="\x00\x00\x00\x00\f\n\nHello Test"
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read HEADERS flags=END_STREAM|END_HEADERS stream=1 len=30
2022/03/03 17:36:28 http2: decoded hpack field header field "grpc-status" = "0" (sensitive)
2022/03/03 17:36:28 http2: decoded hpack field header field "grpc-message" = "" (sensitive)
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote WINDOW_UPDATE len=4 (conn) incr=17
Hello Test
READY
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2022/03/03 17:36:28 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2022/03/03 17:36:38 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:36:38 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:36:48 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:36:48 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:36:58 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:36:58 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:08 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:08 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:18 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:19 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:29 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:29 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:39 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:39 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:49 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:49 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:59 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:37:59 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:09 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:09 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:19 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:19 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:29 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:29 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:39 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:39 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:49 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:49 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:59 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:38:59 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:09 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:09 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:19 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:20 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:30 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:30 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:40 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:40 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:50 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:39:50 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:00 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:00 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:10 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:10 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:20 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:20 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:30 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:30 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:40 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:40 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:50 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:40:50 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:00 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:00 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:10 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:11 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:21 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:21 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:31 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:31 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:41 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:41 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:51 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:41:51 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:01 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:01 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:11 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:11 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:21 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:21 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:31 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:31 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:41 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:41 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:51 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:42:51 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:01 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:01 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:11 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:12 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:22 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:22 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:32 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:32 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:42 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:42 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:52 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:43:52 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:02 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:02 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:12 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:12 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:22 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:22 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:32 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:32 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:42 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:42 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:52 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:44:52 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:02 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:03 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:13 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:13 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:23 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:23 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:33 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:33 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:43 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:43 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:53 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:45:53 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:03 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:03 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:13 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:13 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:23 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:23 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:33 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:33 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:43 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:43 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:53 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:46:53 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:03 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:04 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:14 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:14 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:24 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:24 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:34 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:34 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:44 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:44 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:54 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:47:54 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:04 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:04 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:14 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:14 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:24 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:24 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:34 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:34 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:44 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:44 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:54 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:48:55 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:49:05 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:49:05 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:49:15 http2: Framer 0xc0000d0000: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/03 17:49:15 http2: Framer 0xc0000d0000: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00" Can you share a repro I can try? Regarding pings and the ingress proxy, you are right; pings are not proxies through the proxy. According to this PING frames are only hop-by-hop in HTTP/2 and per-connection, so they won't be proxied. We can add a setting to have the ingress/proxy ping the upstream (app), but the pings will always be either client <-> ingress, or app <-> ingress. For client <-> app pings, that will need apps with tcp transport, which aren't available now. |
Hi @ahmelsayed, Thanks for looking into this and the info on the pings. That matches what I am seeing. I think what I am seeing is a stream reset rather than an idle connection being closed. The application I am testing with uses a server side streaming call that leaves the stream open. That stream is what is reset after 4 minutes. I will try to reproduce it with a simple example and share it here. Thanks again. |
I was able to reproduce with a gRPC server stream. In this example the client subscribes and waits to receive messages. The server holds the stream open and sends a message on an interval of 10 minutes. I am seeing the client receive a RST_STREAM after 4 minutes. Receiving a notification during this time does seem to extend the timeout. Apologies for the lack of a proper repro earlier. Serverpackage main
import (
"fmt"
"log"
"net"
"sync"
"time"
pb "github.com/RichardLaos/grpc-stream/notify"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
)
type server struct {
pb.UnimplementedNotifyServer
subscribers sync.Map
}
type subscriber struct {
stream pb.Notify_SubscribeServer
done chan<- bool
}
func (s *server) Subscribe(request *pb.Request, stream pb.Notify_SubscribeServer) error {
log.Printf("client subscribed: %s", request.DeviceId)
done := make(chan bool)
s.subscribers.Store(request.DeviceId, subscriber{stream: stream, done: done})
ctx := stream.Context()
for {
select {
case <-done:
return nil
case <-ctx.Done():
// client disconnected
return nil
}
}
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
MinTime: 10 * time.Second,
PermitWithoutStream: true,
}),
grpc.KeepaliveParams(keepalive.ServerParameters{
Time: 10 * time.Second,
Timeout: 15 * time.Second,
}),
)
ns := &server{}
go ns.sendNotifications()
pb.RegisterNotifyServer(s, ns)
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func (s *server) sendNotifications() {
for {
time.Sleep(10 * time.Minute)
var unsubscribe []string
s.subscribers.Range(func(k, v interface{}) bool {
id, ok := k.(string)
if !ok {
return false
}
sub, ok := v.(subscriber)
if !ok {
return false
}
// Send data over the gRPC stream to the client
if err := sub.stream.Send(&pb.Notification{Message: fmt.Sprintf("Notification for: %s", id)}); err != nil {
select {
case sub.done <- true:
default:
// avoid blocking
}
unsubscribe = append(unsubscribe, id)
}
return true
})
// Unsubscribe
for _, id := range unsubscribe {
s.subscribers.Delete(id)
}
}
} Clientpackage main
import (
"context"
"crypto/tls"
"log"
"time"
pb "github.com/RichardLaos/grpc-stream/notify"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
)
func main() {
keepaliveParams := keepalive.ClientParameters{
Time: 5 * time.Second,
Timeout: 5 * time.Second,
PermitWithoutStream: true,
}
conn, err := grpc.Dial("stream-server.proudflower-378ee8a3.canadacentral.azurecontainerapps.io:443",
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithKeepaliveParams(keepaliveParams))
if err != nil {
panic(err)
}
defer conn.Close()
c := client{
client: pb.NewNotifyClient(conn),
id: "notify-client-1",
}
c.listen()
}
type client struct {
client pb.NotifyClient
id string
}
func (c *client) listen() {
var err error
var stream pb.Notify_SubscribeClient
for {
if stream == nil {
if stream, err = c.client.Subscribe(context.Background(), &pb.Request{DeviceId: c.id}); err != nil {
log.Printf("failed to subscribe: %v", err)
<-time.After(5 * time.Second)
// Retry on failure
continue
}
}
response, err := stream.Recv()
if err != nil {
log.Printf("failed to receive: %v", err)
// Clearing the stream will force the client to resubscribe on next iteration
stream = nil
<-time.After(5 * time.Second)
// Retry on failure
continue
}
log.Printf("device %s got response: %q", c.id, response.Message)
}
} Client Logs2022/03/04 11:31:13 http2: Framer 0xc00021e540: wrote SETTINGS len=0
2022/03/04 11:31:13 http2: Framer 0xc00021e540: read SETTINGS len=24, settings: HEADER_TABLE_SIZE=4096, UNKNOWN_SETTING_8=0, MAX_CONCURREN
T_STREAMS=100, INITIAL_WINDOW_SIZE=65536
2022/03/04 11:31:13 http2: Framer 0xc00021e540: read WINDOW_UPDATE len=4 (conn) incr=983041
2022/03/04 11:31:13 http2: Framer 0xc00021e540: wrote SETTINGS flags=ACK len=0
2022/03/04 11:31:13 http2: Framer 0xc00021e540: read SETTINGS flags=ACK len=0
2022/03/04 11:31:13 http2: Framer 0xc00021e540: wrote HEADERS flags=END_HEADERS stream=1 len=115
2022/03/04 11:31:13 http2: Framer 0xc00021e540: wrote DATA flags=END_STREAM stream=1 len=22 data="\x00\x00\x00\x00\x11\n\x0fnotify-client-
1"
2022/03/04 11:31:23 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:23 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:33 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:33 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:43 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:43 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:53 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:31:53 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:03 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:03 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:13 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:13 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:23 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:23 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:34 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:34 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:44 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:44 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:54 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:32:54 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:04 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:04 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:14 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:14 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:24 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:24 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:34 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:34 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:44 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:44 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:54 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:33:54 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:04 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:04 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:14 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:15 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:25 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:25 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:35 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:35 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:45 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:45 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:55 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:34:55 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:35:05 http2: Framer 0xc00021e540: wrote PING len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:35:05 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 11:35:13 http2: Framer 0xc00021e540: read HEADERS flags=END_STREAM|END_HEADERS stream=1 len=72
2022/03/04 11:35:13 http2: decoded hpack field header field ":status" = "200"
2022/03/04 11:35:13 http2: decoded hpack field header field "content-type" = "application/grpc"
2022/03/04 11:35:13 http2: decoded hpack field header field "grpc-status" = "2"
2022/03/04 11:35:13 http2: decoded hpack field header field "grpc-message" = "stream timeout"
2022/03/04 11:35:13 http2: decoded hpack field header field "date" = "Fri, 04 Mar 2022 19:35:13 GMT"
2022/03/04 11:35:13 failed to receive: rpc error: code = Unknown desc = stream timeout |
Sometimes the error is due to the stream timeout as in the above log. Others it is a RST_STREAM like below: 2022/03/04 16:06:35 http2: Framer 0xc00021e540: read PING flags=ACK len=8 ping="\x00\x00\x00\x00\x00\x00\x00\x00"
2022/03/04 16:06:37 http2: Framer 0xc00021e540: read RST_STREAM stream=121 len=4 ErrCode=NO_ERROR
2022/03/04 16:06:37 failed to receive: rpc error: code = Internal desc = stream terminated by RST_STREAM with error code: NO_ERROR |
@ahmelsayed Were you able to repro with the new example? |
@RichardLaos, Sorry for not getting back to you, and thank you very much for the repro details. HTTP2 PING are used to verify peer-to-peer connections, and not proxied[1][2]. GRPC KeepAlive uses HTTP2 PING to ensure the connection is alive. That doesn't ensure that the streams carried over the connection will remain alive because the connection is between peers, while the stream is end-to-end. For example, envoy (and other proxies) have timeouts on connections and streams. i.e:
with Today we have a nonconfigurable 4 minutes idleTimeout for
|
@ahmelsayed Thanks for looking into this. The behavior behind a proxy does make sense and the connection itself does stay alive. I am not sure if an application level ping would be more efficient that the rebuilding of the stream when it times out. Both require management of the stream on the server side. A configurable |
Looks like this was tagged "won't fix". I am closing the issue. If you feel like it hasn't been resolved, feel free to reopen. Thanks! |
When running a gRPC application that is configured to send http2 keep alive pings the container app will timeout a stream after 4 minutes. This can be seen in the following http2 trace:
This reset is not being sent by the gRPC service itself. Also, it appears the the ingress does not forward the http2 pings between the container instance and the client (it does seem to respond to a ping). When connected directly to the service the trace looks like this:
Note that it is reading both PINGs and PING ACKs. Also, when connected directly to the service the stream does not reset.
This seems to be dictated by the ingress configuration. Will there be some way to configure this in the future?
The text was updated successfully, but these errors were encountered: