Skip to content
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

Merged
merged 10 commits into from
Dec 6, 2024

Conversation

purnesh42H
Copy link
Contributor

@purnesh42H purnesh42H commented Nov 22, 2024

Fixes: #7843

RELEASE NOTES: None

Copy link

codecov bot commented Nov 22, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.99%. Comparing base (87f0254) to head (0b880da).
Report is 22 commits behind head on master.

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     

see 40 files with indirect coverage changes

@purnesh42H purnesh42H added the Type: Documentation Documentation or examples label Nov 22, 2024
@purnesh42H purnesh42H added this to the 1.69 Release milestone Nov 22, 2024
@bkane-msft
Copy link

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().
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backticks?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Server.GracefulStop().
`Server.GracefulStop()`.

Copy link

@bkane-msft bkane-msft Nov 22, 2024

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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: an interrupt signal

Copy link
Contributor Author

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: the server

Copy link
Contributor Author

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.
Copy link
Member

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".)

Copy link
Contributor Author

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.
Copy link
Member

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.

Copy link
Contributor Author

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.

Comment on lines 42 to 44
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
Copy link
Member

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.

Copy link
Contributor Author

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++ {
Copy link
Member

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?

Copy link
Contributor Author

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)
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@dfawley dfawley assigned purnesh42H and unassigned dfawley and arjan-bal Nov 22, 2024
@purnesh42H purnesh42H force-pushed the example-gracefulstop branch 4 times, most recently from 34c46e8 to 96ebe95 Compare November 25, 2024 05:57
@purnesh42H
Copy link
Contributor Author

purnesh42H commented Nov 25, 2024

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?

@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.

@purnesh42H purnesh42H requested a review from dfawley November 25, 2024 06:15
@purnesh42H purnesh42H assigned dfawley and unassigned purnesh42H Nov 25, 2024
Comment on lines 63 to 65
if streamMessages > 5 {
return fmt.Errorf("request failed")
}
Copy link
Member

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.

Copy link
Contributor Author

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()
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applicable now

@dfawley dfawley assigned purnesh42H and unassigned dfawley Nov 25, 2024
@bkane-msft
Copy link

@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!

@purnesh42H purnesh42H requested a review from dfawley November 27, 2024 13:36
@purnesh42H purnesh42H requested a review from dfawley November 28, 2024 17:08
@purnesh42H purnesh42H assigned dfawley and unassigned purnesh42H Nov 28, 2024
Copy link
Member

@dfawley dfawley left a 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

@dfawley dfawley assigned purnesh42H and unassigned dfawley Dec 2, 2024
@purnesh42H
Copy link
Contributor Author

The example LGTM. Please add coverage for it in examples_test.sh

Added

@purnesh42H purnesh42H requested a review from dfawley December 3, 2024 04:19
@purnesh42H purnesh42H assigned dfawley and unassigned purnesh42H Dec 3, 2024
@purnesh42H purnesh42H modified the milestones: 1.69 Release, 1.70 Release Dec 5, 2024
@@ -71,6 +71,7 @@ EXAMPLES=(
"features/orca"
"features/retry"
"features/unix_abstract"
"features/gracefulstop"
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. PTAL

@dfawley dfawley assigned purnesh42H and unassigned dfawley Dec 5, 2024
@purnesh42H purnesh42H force-pushed the example-gracefulstop branch from 91c01e0 to 0b880da Compare December 5, 2024 17:12
@purnesh42H purnesh42H requested a review from dfawley December 5, 2024 17:18
@purnesh42H purnesh42H assigned dfawley and unassigned purnesh42H Dec 5, 2024
@dfawley dfawley assigned purnesh42H and unassigned dfawley Dec 5, 2024
@dfawley
Copy link
Member

dfawley commented Dec 5, 2024

LGTM. Should the PR comment 0 say "Fixes #7843" instead so it's closed?

@purnesh42H
Copy link
Contributor Author

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.

@purnesh42H purnesh42H merged commit 66ba4b2 into grpc:master Dec 6, 2024
15 checks passed
purnesh42H added a commit to purnesh42H/grpc-go that referenced this pull request Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Documentation Documentation or examples
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Example code doesn't gracefully shutdown
4 participants