Skip to content

Commit 9f64710

Browse files
author
maxinglun
committedApr 28, 2022
fix: consume and publish blocked after rabbitmq reconnecting
1 parent fe827c4 commit 9f64710

File tree

2 files changed

+40
-34
lines changed

2 files changed

+40
-34
lines changed
 

‎v4/broker/rabbitmq/connection.go

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -129,42 +129,35 @@ func (r *rabbitMQConn) reconnect(secure bool, config *amqp.Config) {
129129
chanNotifyClose := make(chan *amqp.Error)
130130
channel := r.ExchangeChannel.channel
131131
channel.NotifyClose(chanNotifyClose)
132-
channelNotifyReturn := make(chan amqp.Return)
133-
channel.NotifyReturn(channelNotifyReturn)
134-
135-
// block until closed
136-
select {
137-
case result, ok := <-channelNotifyReturn:
138-
if !ok {
139-
// Channel closed, probably also the channel or connection.
132+
// To avoid deadlocks it is necessary to consume the messages from all channels.
133+
for notifyClose != nil || chanNotifyClose != nil {
134+
// block until closed
135+
select {
136+
case err := <-chanNotifyClose:
137+
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
138+
logger.Error(err)
139+
}
140+
// block all resubscribe attempt - they are useless because there is no connection to rabbitmq
141+
// create channel 'waitConnection' (at this point channel is nil or closed, create it without unnecessary checks)
142+
r.Lock()
143+
r.connected = false
144+
r.waitConnection = make(chan struct{})
145+
r.Unlock()
146+
chanNotifyClose = nil
147+
case err := <-notifyClose:
148+
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
149+
logger.Error(err)
150+
}
151+
// block all resubscribe attempt - they are useless because there is no connection to rabbitmq
152+
// create channel 'waitConnection' (at this point channel is nil or closed, create it without unnecessary checks)
153+
r.Lock()
154+
r.connected = false
155+
r.waitConnection = make(chan struct{})
156+
r.Unlock()
157+
notifyClose = nil
158+
case <-r.close:
140159
return
141160
}
142-
// Do what you need with messageFailing.
143-
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
144-
logger.Errorf("notify error reason: %s, description: %s", result.ReplyText, result.Exchange)
145-
}
146-
case err := <-chanNotifyClose:
147-
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
148-
logger.Error(err)
149-
}
150-
// block all resubscribe attempt - they are useless because there is no connection to rabbitmq
151-
// create channel 'waitConnection' (at this point channel is nil or closed, create it without unnecessary checks)
152-
r.Lock()
153-
r.connected = false
154-
r.waitConnection = make(chan struct{})
155-
r.Unlock()
156-
case err := <-notifyClose:
157-
if logger.V(logger.ErrorLevel, logger.DefaultLogger) {
158-
logger.Error(err)
159-
}
160-
// block all resubscribe attempt - they are useless because there is no connection to rabbitmq
161-
// create channel 'waitConnection' (at this point channel is nil or closed, create it without unnecessary checks)
162-
r.Lock()
163-
r.connected = false
164-
r.waitConnection = make(chan struct{})
165-
r.Unlock()
166-
case <-r.close:
167-
return
168161
}
169162
}
170163
}

‎v4/broker/rabbitmq/rabbitmq.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ func (s *subscriber) resubscribe() {
102102
return
103103
//wait until we reconect to rabbit
104104
case <-s.r.conn.waitConnection:
105+
// When the connection is disconnected, the waitConnection will be re-assigned, so '<-s.r.conn.waitConnection' maybe blocked.
106+
// Here, it returns once a second, and then the latest waitconnection will be used
107+
case <-time.After(time.Second):
108+
continue
105109
}
106110

107111
// it may crash (panic) in case of Consume without connection, so recheck it
@@ -267,6 +271,15 @@ func (r *rbroker) Subscribe(topic string, handler broker.Handler, opts ...broker
267271
for k, v := range msg.Headers {
268272
header[k], _ = v.(string)
269273
}
274+
275+
// Messages sent from other frameworks to rabbitmq do not have this header.
276+
// The 'RoutingKey' in the message can be used as this header.
277+
// Then the message can be transfered to the subscriber which bind this topic.
278+
msgTopic := header["Micro-Topic"]
279+
if msgTopic == "" {
280+
header["Micro-Topic"] = msg.RoutingKey
281+
}
282+
270283
m := &broker.Message{
271284
Header: header,
272285
Body: msg.Body,

0 commit comments

Comments
 (0)
Please sign in to comment.