-
Notifications
You must be signed in to change notification settings - Fork 33
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
Improve broker initiated client disconnects #816
Changes from 16 commits
f8a0fca
9e9f30d
81497d4
f5b8191
39d2f60
fb106ee
18162fe
08dd6b4
7961ff6
8af808e
713f10d
e4d206e
7147320
f359792
26871ea
4d17800
2ab2804
7e642d9
1bed6af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -369,18 +369,54 @@ module LavinMQ | |
upstreams.stop_all | ||
end | ||
|
||
private def close_connections(reason) | ||
WaitGroup.wait do |wg| | ||
to_close = Channel(Client).new | ||
fiber_count = 0 | ||
@connections.each do |client| | ||
loop do | ||
select | ||
when to_close.send client | ||
break | ||
else | ||
fiber_id = fiber_count &+= 1 | ||
@log.trace { "spawning close conn fiber #{fiber_id} " } | ||
wg.spawn do | ||
while client_to_close = to_close.receive? | ||
client_to_close.close(reason) | ||
end | ||
@log.trace { "exiting close conn fiber #{fiber_id} " } | ||
end | ||
Fiber.yield | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Required? Doesn't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why, but it did spawn one extra fiber. Not a big deal, but... |
||
end | ||
end | ||
end | ||
to_close.close | ||
end | ||
end | ||
|
||
def close(reason = "Broker shutdown") | ||
@closed = true | ||
stop_shovels | ||
stop_upstream_links | ||
Fiber.yield | ||
@log.debug { "Closing connections" } | ||
@connections.each &.close(reason) | ||
# wait up to 10s for clients to gracefully close | ||
100.times do | ||
break if @connections.empty? | ||
sleep 0.1.seconds | ||
|
||
@log.info { "Closing connections" } | ||
close_done = Channel(Nil).new | ||
|
||
spawn do | ||
close_connections reason | ||
@log.debug { "Close sent to all connections" } | ||
close_done.close | ||
end | ||
|
||
select | ||
when close_done.receive? | ||
@log.info { "All connections closed gracefully" } | ||
when timeout 5.seconds | ||
@log.warn { "Timeout waiting for connections to close. #{@connections.size} left." } | ||
end | ||
spuun marked this conversation as resolved.
Show resolved
Hide resolved
|
||
close_done.close | ||
|
||
# then force close the remaining (close tcp socket) | ||
@connections.each &.force_close | ||
Fiber.yield # yield so that Client read_loops can shutdown | ||
|
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.
We could make a PR to the stdlib so that we can name fibers spawned by
WaitGroup#spawn
.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.
Agree.
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.
PR sent.