25
25
import java .util .Map ;
26
26
import java .util .Map .Entry ;
27
27
import java .util .concurrent .ConcurrentHashMap ;
28
+ import java .util .concurrent .ConcurrentMap ;
28
29
import java .util .concurrent .CopyOnWriteArrayList ;
29
30
import org .apache .rocketmq .broker .util .PositiveAtomicCounter ;
30
31
import org .apache .rocketmq .common .constant .LoggerName ;
@@ -39,11 +40,11 @@ public class ProducerManager {
39
40
private static final Logger log = LoggerFactory .getLogger (LoggerName .BROKER_LOGGER_NAME );
40
41
private static final long CHANNEL_EXPIRED_TIMEOUT = 1000 * 120 ;
41
42
private static final int GET_AVAILABLE_CHANNEL_RETRY_COUNT = 3 ;
42
- private final ConcurrentHashMap <String /* group name */ , ConcurrentHashMap <Channel , ClientChannelInfo >> groupChannelTable =
43
+ private final ConcurrentMap <String /* group name */ , ConcurrentMap <Channel , ClientChannelInfo >> groupChannelTable =
43
44
new ConcurrentHashMap <>();
44
- private final ConcurrentHashMap <String , Channel > clientChannelTable = new ConcurrentHashMap <>();
45
+ private final ConcurrentMap <String , Channel > clientChannelTable = new ConcurrentHashMap <>();
45
46
protected final BrokerStatsManager brokerStatsManager ;
46
- private PositiveAtomicCounter positiveAtomicCounter = new PositiveAtomicCounter ();
47
+ private final PositiveAtomicCounter positiveAtomicCounter = new PositiveAtomicCounter ();
47
48
private final List <ProducerChangeListener > producerChangeListenerList = new CopyOnWriteArrayList <>();
48
49
49
50
public ProducerManager () {
@@ -63,22 +64,22 @@ public boolean groupOnline(String group) {
63
64
return channels != null && !channels .isEmpty ();
64
65
}
65
66
66
- public ConcurrentHashMap <String , ConcurrentHashMap <Channel , ClientChannelInfo >> getGroupChannelTable () {
67
+ public ConcurrentMap <String , ConcurrentMap <Channel , ClientChannelInfo >> getGroupChannelTable () {
67
68
return groupChannelTable ;
68
69
}
69
70
70
71
public ProducerTableInfo getProducerTable () {
71
72
Map <String , List <ProducerInfo >> map = new HashMap <>();
72
73
for (String group : this .groupChannelTable .keySet ()) {
73
- for (Entry <Channel , ClientChannelInfo > entry : this .groupChannelTable .get (group ).entrySet ()) {
74
+ for (Entry <Channel , ClientChannelInfo > entry : this .groupChannelTable .get (group ).entrySet ()) {
74
75
ClientChannelInfo clientChannelInfo = entry .getValue ();
75
76
if (map .containsKey (group )) {
76
77
map .get (group ).add (new ProducerInfo (
77
- clientChannelInfo .getClientId (),
78
- clientChannelInfo .getChannel ().remoteAddress ().toString (),
79
- clientChannelInfo .getLanguage (),
80
- clientChannelInfo .getVersion (),
81
- clientChannelInfo .getLastUpdateTimestamp ()
78
+ clientChannelInfo .getClientId (),
79
+ clientChannelInfo .getChannel ().remoteAddress ().toString (),
80
+ clientChannelInfo .getLanguage (),
81
+ clientChannelInfo .getVersion (),
82
+ clientChannelInfo .getLastUpdateTimestamp ()
82
83
));
83
84
} else {
84
85
map .put (group , new ArrayList <>(Collections .singleton (new ProducerInfo (
@@ -95,13 +96,13 @@ public ProducerTableInfo getProducerTable() {
95
96
}
96
97
97
98
public void scanNotActiveChannel () {
98
- Iterator <Map .Entry <String , ConcurrentHashMap <Channel , ClientChannelInfo >>> iterator = this .groupChannelTable .entrySet ().iterator ();
99
+ Iterator <Map .Entry <String , ConcurrentMap <Channel , ClientChannelInfo >>> iterator = this .groupChannelTable .entrySet ().iterator ();
99
100
100
101
while (iterator .hasNext ()) {
101
- Map .Entry <String , ConcurrentHashMap <Channel , ClientChannelInfo >> entry = iterator .next ();
102
+ Map .Entry <String , ConcurrentMap <Channel , ClientChannelInfo >> entry = iterator .next ();
102
103
103
104
final String group = entry .getKey ();
104
- final ConcurrentHashMap <Channel , ClientChannelInfo > chlMap = entry .getValue ();
105
+ final ConcurrentMap <Channel , ClientChannelInfo > chlMap = entry .getValue ();
105
106
106
107
Iterator <Entry <Channel , ClientChannelInfo >> it = chlMap .entrySet ().iterator ();
107
108
while (it .hasNext ()) {
@@ -117,8 +118,8 @@ public void scanNotActiveChannel() {
117
118
clientChannelTable .remove (info .getClientId ());
118
119
}
119
120
log .warn (
120
- "ProducerManager#scanNotActiveChannel: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}" ,
121
- RemotingHelper .parseChannelRemoteAddr (info .getChannel ()), group );
121
+ "ProducerManager#scanNotActiveChannel: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}" ,
122
+ RemotingHelper .parseChannelRemoteAddr (info .getChannel ()), group );
122
123
callProducerChangeListener (ProducerGroupEvent .CLIENT_UNREGISTER , group , info );
123
124
RemotingHelper .closeChannel (info .getChannel ());
124
125
}
@@ -132,25 +133,22 @@ public void scanNotActiveChannel() {
132
133
}
133
134
}
134
135
135
- public synchronized boolean doChannelCloseEvent (final String remoteAddr , final Channel channel ) {
136
+ public boolean doChannelCloseEvent (final String remoteAddr , final Channel channel ) {
136
137
boolean removed = false ;
137
138
if (channel != null ) {
138
- for (final Map .Entry <String , ConcurrentHashMap <Channel , ClientChannelInfo >> entry : this .groupChannelTable
139
- .entrySet ()) {
139
+ for (final Map .Entry <String , ConcurrentMap <Channel , ClientChannelInfo >> entry : this .groupChannelTable .entrySet ()) {
140
140
final String group = entry .getKey ();
141
- final ConcurrentHashMap <Channel , ClientChannelInfo > clientChannelInfoTable =
142
- entry .getValue ();
143
- final ClientChannelInfo clientChannelInfo =
144
- clientChannelInfoTable .remove (channel );
141
+ final ConcurrentMap <Channel , ClientChannelInfo > clientChannelInfoTable = entry .getValue ();
142
+ final ClientChannelInfo clientChannelInfo = clientChannelInfoTable .remove (channel );
145
143
if (clientChannelInfo != null ) {
146
144
clientChannelTable .remove (clientChannelInfo .getClientId ());
147
145
removed = true ;
148
146
log .info (
149
- "NETTY EVENT: remove channel[{}][{}] from ProducerManager groupChannelTable, producer group: {}" ,
150
- clientChannelInfo .toString (), remoteAddr , group );
147
+ "NETTY EVENT: remove channel[{}][{}] from ProducerManager groupChannelTable, producer group: {}" ,
148
+ clientChannelInfo .toString (), remoteAddr , group );
151
149
callProducerChangeListener (ProducerGroupEvent .CLIENT_UNREGISTER , group , clientChannelInfo );
152
150
if (clientChannelInfoTable .isEmpty ()) {
153
- ConcurrentHashMap <Channel , ClientChannelInfo > oldGroupTable = this .groupChannelTable .remove (group );
151
+ ConcurrentMap <Channel , ClientChannelInfo > oldGroupTable = this .groupChannelTable .remove (group );
154
152
if (oldGroupTable != null ) {
155
153
log .info ("unregister a producer group[{}] from groupChannelTable" , group );
156
154
callProducerChangeListener (ProducerGroupEvent .GROUP_UNREGISTER , group , null );
@@ -163,37 +161,44 @@ public synchronized boolean doChannelCloseEvent(final String remoteAddr, final C
163
161
return removed ;
164
162
}
165
163
166
- public synchronized void registerProducer (final String group , final ClientChannelInfo clientChannelInfo ) {
167
- ClientChannelInfo clientChannelInfoFound = null ;
164
+ public void registerProducer (final String group , final ClientChannelInfo clientChannelInfo ) {
165
+ ClientChannelInfo clientChannelInfoFound ;
168
166
169
- ConcurrentHashMap <Channel , ClientChannelInfo > channelTable = this .groupChannelTable .get (group );
167
+ ConcurrentMap <Channel , ClientChannelInfo > channelTable = this .groupChannelTable .get (group );
170
168
if (null == channelTable ) {
171
169
channelTable = new ConcurrentHashMap <>();
172
- this .groupChannelTable .put (group , channelTable );
170
+ // Make sure channelTable will NOT be cleaned by #scanNotActiveChannel
171
+ channelTable .put (clientChannelInfo .getChannel (), clientChannelInfo );
172
+ ConcurrentMap <Channel , ClientChannelInfo > prev = this .groupChannelTable .putIfAbsent (group , channelTable );
173
+ if (null == prev ) {
174
+ // Add client-id to channel mapping for new producer group
175
+ clientChannelTable .put (clientChannelInfo .getClientId (), clientChannelInfo .getChannel ());
176
+ } else {
177
+ channelTable = prev ;
178
+ }
173
179
}
174
180
175
181
clientChannelInfoFound = channelTable .get (clientChannelInfo .getChannel ());
182
+ // Add client-channel info to existing producer group
176
183
if (null == clientChannelInfoFound ) {
177
184
channelTable .put (clientChannelInfo .getChannel (), clientChannelInfo );
178
185
clientChannelTable .put (clientChannelInfo .getClientId (), clientChannelInfo .getChannel ());
179
- log .info ("new producer connected, group: {} channel: {}" , group ,
180
- clientChannelInfo .toString ());
186
+ log .info ("new producer connected, group: {} channel: {}" , group , clientChannelInfo .toString ());
181
187
}
182
188
183
-
189
+ // Refresh existing client-channel-info update-timestamp
184
190
if (clientChannelInfoFound != null ) {
185
191
clientChannelInfoFound .setLastUpdateTimestamp (System .currentTimeMillis ());
186
192
}
187
193
}
188
194
189
- public synchronized void unregisterProducer (final String group , final ClientChannelInfo clientChannelInfo ) {
190
- ConcurrentHashMap <Channel , ClientChannelInfo > channelTable = this .groupChannelTable .get (group );
195
+ public void unregisterProducer (final String group , final ClientChannelInfo clientChannelInfo ) {
196
+ ConcurrentMap <Channel , ClientChannelInfo > channelTable = this .groupChannelTable .get (group );
191
197
if (null != channelTable && !channelTable .isEmpty ()) {
192
198
ClientChannelInfo old = channelTable .remove (clientChannelInfo .getChannel ());
193
199
clientChannelTable .remove (clientChannelInfo .getClientId ());
194
200
if (old != null ) {
195
- log .info ("unregister a producer[{}] from groupChannelTable {}" , group ,
196
- clientChannelInfo .toString ());
201
+ log .info ("unregister a producer[{}] from groupChannelTable {}" , group , clientChannelInfo .toString ());
197
202
callProducerChangeListener (ProducerGroupEvent .CLIENT_UNREGISTER , group , clientChannelInfo );
198
203
}
199
204
@@ -210,7 +215,7 @@ public Channel getAvailableChannel(String groupId) {
210
215
return null ;
211
216
}
212
217
List <Channel > channelList ;
213
- ConcurrentHashMap <Channel , ClientChannelInfo > channelClientChannelInfoHashMap = groupChannelTable .get (groupId );
218
+ ConcurrentMap <Channel , ClientChannelInfo > channelClientChannelInfoHashMap = groupChannelTable .get (groupId );
214
219
if (channelClientChannelInfoHashMap != null ) {
215
220
channelList = new ArrayList <>(channelClientChannelInfoHashMap .keySet ());
216
221
} else {
0 commit comments