-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
examples/features/gracefulstop: add example to demonstrate server graceful stop #7865
Conversation
c120ffd
to
6b8ce78
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #7865 +/- ##
==========================================
+ Coverage 81.74% 81.99% +0.25%
==========================================
Files 375 377 +2
Lines 37980 38179 +199
==========================================
+ Hits 31045 31306 +261
+ Misses 5622 5565 -57
+ Partials 1313 1308 -5 |
This looks great, thank you! Would you ok linking to this example from https://grpc.io/docs/languages/go/basics/#starting-the-server so folks following the "Basics" tutorial can easily find it? |
# Graceful Stop | ||
|
||
This example demonstrates how to gracefully stop a gRPC server using | ||
Server.GracefulStop(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backticks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Server.GracefulStop(). | |
`Server.GracefulStop()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub has a somewhat hidden feature that lets you offer suggestions by editing the text selected in the comment box . Then the PR author can click "accept" right there in the comment thread instead of checking out the repo and editing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added backticks. Thanks
## How to run | ||
|
||
Start the server which will listen to incoming gRPC requests as well as OS | ||
interrupt signals (SIGINT/SIGTERM). After receiving interrupt signal, it calls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar: an interrupt signal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Start the server which will listen to incoming gRPC requests as well as OS | ||
interrupt signals (SIGINT/SIGTERM). After receiving interrupt signal, it calls | ||
`s.GracefulStop()` to gracefully shut down the server. If graceful shutdown | ||
doesn't happen in time, server is stopped forcefully. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar: the server
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Use Ctrl+C or SIGTERM to signal the server to shut down. | ||
|
||
The server begins a graceful stop: | ||
- It finishes ongoing requests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: ongoing -> in flight / in progress
("Ongoing" means more like "continuous".)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-wrote the description as the logic is changed now. Using in-flight though.
|
||
The server begins a graceful stop: | ||
- It finishes ongoing requests. | ||
- Rejects new incoming requests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how precise we want to be here, but this isn't exactly what happens, FYI.
The server sends a GOAWAY on the connection, which the client sees, and then the client will stop sending requests on the connection. If the client ignores the GOAWAY, then the server will reject new streams, but that shouldn't actually happen in any properly functioning HTTP/2 system.
What you wrote might be good enough for a basics explanation though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Now i am just restricting the description to completing the in-flight requests because we are not demonstrating sending new request while server is shutting down.
if err != nil { | ||
log.Fatalf("Failed to connect: %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: NewClient
doesn't connect. The only errors you'd get here would be providing illegal options to the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
for i := 1; i <= 10; i++ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the client do these until they fail with Unavailable
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, client now waits until receiving an error from server. Explained above.
<-stop | ||
fmt.Println("Shutting down server...") | ||
s.GracefulStop() | ||
close(stop) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this OK? Closing the channel given to signal.Notify
? What if ^C is pressed again after the channel is closed? Wouldn't it panic?
Better to just do a timer := time.AfterFunc(10*time.Second, s.Stop); defer timer.Stop(); s.GracefulStop()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
34c46e8
to
96ebe95
Compare
@bkane-msft the basic tutorial might not be appropriate for a graceful stop example as it is slightly advanced in nature. Right now we are proposing to add it as a cross-language "guide" https://grpc.io/docs/guides/. Will update here. |
96ebe95
to
d48bd1f
Compare
if streamMessages > 5 { | ||
return fmt.Errorf("request failed") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why return an error? Exiting successfully feels more graceful.
Also you should always return status errors from your method handlers. This will get converted to UNKNOWN by gRPC, which "is fine", but we should never show an example that does anything but send statuses back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not applicable now. Explained the flow above
if err != nil { | ||
// Handle the error and close the stream gracefully | ||
log.Printf("Error sending request: %v\n", err) | ||
err := stream.CloseSend() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense. The stream ended (by virtue of receiving an error), so there is no reason to CloseSend
. Probably CloseSend
should also return an error in this scenario, but it's also probably not important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not applicable now
@purnesh42H and @dfawley , as someone new to gRPC, I'm really grateful to you two for your hard work in this PR providing a correct production-ready shutdown example! Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example LGTM. Please add coverage for it in examples_test.sh
Added |
@@ -71,6 +71,7 @@ EXAMPLES=( | |||
"features/orca" | |||
"features/retry" | |||
"features/unix_abstract" | |||
"features/gracefulstop" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs expectations for server and/or client output to confirm it is working correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added. PTAL
91c01e0
to
0b880da
Compare
LGTM. Should the PR comment 0 say "Fixes #7843" instead so it's closed? |
yeah we can close this issue but I think we should link it through grpc.io docs with similar guidelines for server graceful stop. |
Fixes: #7843
RELEASE NOTES: None