1717
1818package org .apache .rocketmq .broker .longpolling ;
1919
20- import com .googlecode .concurrentlinkedhashmap .ConcurrentLinkedHashMap ;
20+ import com .github .benmanes .caffeine .cache .Cache ;
21+ import com .github .benmanes .caffeine .cache .Caffeine ;
2122import io .netty .channel .ChannelHandlerContext ;
2223import java .util .ArrayList ;
2324import java .util .Iterator ;
2425import java .util .Map ;
2526import java .util .concurrent .ConcurrentHashMap ;
2627import java .util .concurrent .ConcurrentSkipListSet ;
28+ import java .util .concurrent .TimeUnit ;
2729import java .util .concurrent .atomic .AtomicLong ;
2830import org .apache .rocketmq .broker .BrokerController ;
2931import org .apache .rocketmq .common .KeyBuilder ;
@@ -52,21 +54,27 @@ public class PopLongPollingService extends ServiceThread {
5254 LoggerFactory .getLogger (LoggerName .ROCKETMQ_POP_LOGGER_NAME );
5355 private final BrokerController brokerController ;
5456 private final NettyRequestProcessor processor ;
55- private final ConcurrentLinkedHashMap <String , ConcurrentHashMap <String , Byte >> topicCidMap ;
56- private final ConcurrentLinkedHashMap <String , ConcurrentSkipListSet <PopRequest >> pollingMap ;
57+ private final Cache <String , ConcurrentHashMap <String , Byte >> topicCidMap ;
58+ private final Cache <String , ConcurrentSkipListSet <PopRequest >> pollingMap ;
5759 private long lastCleanTime = 0 ;
5860
5961 private final AtomicLong totalPollingNum = new AtomicLong (0 );
6062 private final boolean notifyLast ;
6163
62- public PopLongPollingService (BrokerController brokerController , NettyRequestProcessor processor , boolean notifyLast ) {
64+ public PopLongPollingService (BrokerController brokerController , NettyRequestProcessor processor ,
65+ boolean notifyLast ) {
6366 this .brokerController = brokerController ;
6467 this .processor = processor ;
6568 // 100000 topic default, 100000 lru topic + cid + qid
66- this .topicCidMap = new ConcurrentLinkedHashMap .Builder <String , ConcurrentHashMap <String , Byte >>()
67- .maximumWeightedCapacity (this .brokerController .getBrokerConfig ().getPopPollingMapSize () * 2L ).build ();
68- this .pollingMap = new ConcurrentLinkedHashMap .Builder <String , ConcurrentSkipListSet <PopRequest >>()
69- .maximumWeightedCapacity (this .brokerController .getBrokerConfig ().getPopPollingMapSize ()).build ();
69+ this .topicCidMap = Caffeine .newBuilder ()
70+ .maximumSize (this .brokerController .getBrokerConfig ().getPopPollingMapSize () * 2L )
71+ .expireAfterAccess (this .brokerController .getBrokerConfig ().getPopPollingMapExpireTimeSeconds (), TimeUnit .SECONDS )
72+ .build ();
73+
74+ this .pollingMap = Caffeine .newBuilder ()
75+ .maximumSize (this .brokerController .getBrokerConfig ().getPopPollingMapSize ())
76+ .expireAfterAccess (this .brokerController .getBrokerConfig ().getPopPollingMapExpireTimeSeconds (), TimeUnit .SECONDS )
77+ .build ();
7078 this .notifyLast = notifyLast ;
7179 }
7280
@@ -85,11 +93,11 @@ public void run() {
8593 try {
8694 this .waitForRunning (20 );
8795 i ++;
88- if (pollingMap .isEmpty () ) {
96+ if (pollingMap .estimatedSize () == 0 ) {
8997 continue ;
9098 }
9199 long tmpTotalPollingNum = 0 ;
92- for (Map .Entry <String , ConcurrentSkipListSet <PopRequest >> entry : pollingMap .entrySet ()) {
100+ for (Map .Entry <String , ConcurrentSkipListSet <PopRequest >> entry : pollingMap .asMap (). entrySet ()) {
93101 String key = entry .getKey ();
94102 ConcurrentSkipListSet <PopRequest > popQ = entry .getValue ();
95103 if (popQ == null ) {
@@ -126,7 +134,7 @@ public void run() {
126134
127135 if (i >= 100 ) {
128136 POP_LOGGER .info ("pollingMapSize={},tmpTotalSize={},atomicTotalSize={},diffSize={}" ,
129- pollingMap .size (), tmpTotalPollingNum , totalPollingNum .get (),
137+ pollingMap .estimatedSize (), tmpTotalPollingNum , totalPollingNum .get (),
130138 Math .abs (totalPollingNum .get () - tmpTotalPollingNum ));
131139 totalPollingNum .set (tmpTotalPollingNum );
132140 i = 0 ;
@@ -142,7 +150,7 @@ public void run() {
142150 }
143151 // clean all;
144152 try {
145- for (Map .Entry <String , ConcurrentSkipListSet <PopRequest >> entry : pollingMap .entrySet ()) {
153+ for (Map .Entry <String , ConcurrentSkipListSet <PopRequest >> entry : pollingMap .asMap (). entrySet ()) {
146154 ConcurrentSkipListSet <PopRequest > popQ = entry .getValue ();
147155 PopRequest first ;
148156 while ((first = popQ .pollFirst ()) != null ) {
@@ -170,7 +178,7 @@ public void notifyMessageArrivingWithRetryTopic(final String topic, final int qu
170178
171179 public void notifyMessageArriving (final String topic , final int queueId , long offset ,
172180 Long tagsCode , long msgStoreTime , byte [] filterBitMap , Map <String , String > properties ) {
173- ConcurrentHashMap <String , Byte > cids = topicCidMap .get (topic );
181+ ConcurrentHashMap <String , Byte > cids = topicCidMap .getIfPresent (topic );
174182 if (cids == null ) {
175183 return ;
176184 }
@@ -196,7 +204,7 @@ public boolean notifyMessageArriving(final String topic, final int queueId, fina
196204
197205 public boolean notifyMessageArriving (final String topic , final int queueId , final String cid , boolean force ,
198206 Long tagsCode , long msgStoreTime , byte [] filterBitMap , Map <String , String > properties , CommandCallback callback ) {
199- ConcurrentSkipListSet <PopRequest > remotingCommands = pollingMap .get (KeyBuilder .buildPollingKey (topic , cid , queueId ));
207+ ConcurrentSkipListSet <PopRequest > remotingCommands = pollingMap .getIfPresent (KeyBuilder .buildPollingKey (topic , cid , queueId ));
200208 if (remotingCommands == null || remotingCommands .isEmpty ()) {
201209 return false ;
202210 }
@@ -286,14 +294,7 @@ public PollingResult polling(final ChannelHandlerContext ctx, RemotingCommand re
286294 if (requestHeader .getPollTime () <= 0 || this .isStopped ()) {
287295 return NOT_POLLING ;
288296 }
289- ConcurrentHashMap <String , Byte > cids = topicCidMap .get (requestHeader .getTopic ());
290- if (cids == null ) {
291- cids = new ConcurrentHashMap <>();
292- ConcurrentHashMap <String , Byte > old = topicCidMap .putIfAbsent (requestHeader .getTopic (), cids );
293- if (old != null ) {
294- cids = old ;
295- }
296- }
297+ ConcurrentHashMap <String , Byte > cids = topicCidMap .get (requestHeader .getTopic (), key -> new ConcurrentHashMap <>());
297298 cids .putIfAbsent (requestHeader .getConsumerGroup (), Byte .MIN_VALUE );
298299 long expired = requestHeader .getBornTime () + requestHeader .getPollTime ();
299300 final PopRequest request = new PopRequest (remotingCommand , ctx , expired , subscriptionData , messageFilter );
@@ -311,21 +312,13 @@ public PollingResult polling(final ChannelHandlerContext ctx, RemotingCommand re
311312 }
312313 String key = KeyBuilder .buildPollingKey (requestHeader .getTopic (), requestHeader .getConsumerGroup (),
313314 requestHeader .getQueueId ());
314- ConcurrentSkipListSet <PopRequest > queue = pollingMap .get (key );
315- if (queue == null ) {
316- queue = new ConcurrentSkipListSet <>(PopRequest .COMPARATOR );
317- ConcurrentSkipListSet <PopRequest > old = pollingMap .putIfAbsent (key , queue );
318- if (old != null ) {
319- queue = old ;
320- }
321- } else {
322- // check size
323- int size = queue .size ();
324- if (size > brokerController .getBrokerConfig ().getPopPollingSize ()) {
325- POP_LOGGER .info ("polling {}, result POLLING_FULL, singleSize:{}" , remotingCommand , size );
326- return POLLING_FULL ;
327- }
315+ ConcurrentSkipListSet <PopRequest > queue = pollingMap .get (key , k -> new ConcurrentSkipListSet <>(PopRequest .COMPARATOR ));
316+ int size = queue .size ();
317+ if (size > brokerController .getBrokerConfig ().getPopPollingSize ()) {
318+ POP_LOGGER .info ("polling {}, result POLLING_FULL, singleSize:{}" , remotingCommand , size );
319+ return POLLING_FULL ;
328320 }
321+
329322 if (queue .add (request )) {
330323 remotingCommand .setSuspended (true );
331324 totalPollingNum .incrementAndGet ();
@@ -339,14 +332,18 @@ public PollingResult polling(final ChannelHandlerContext ctx, RemotingCommand re
339332 }
340333 }
341334
342- public ConcurrentLinkedHashMap <String , ConcurrentSkipListSet <PopRequest >> getPollingMap () {
335+ public Cache <String , ConcurrentSkipListSet <PopRequest >> getPollingMap () {
343336 return pollingMap ;
344337 }
345338
339+ public Cache <String , ConcurrentHashMap <String , Byte >> getTopicCidMap () {
340+ return topicCidMap ;
341+ }
342+
346343 private void cleanUnusedResource () {
347344 try {
348345 {
349- Iterator <Map .Entry <String , ConcurrentHashMap <String , Byte >>> topicCidMapIter = topicCidMap .entrySet ().iterator ();
346+ Iterator <Map .Entry <String , ConcurrentHashMap <String , Byte >>> topicCidMapIter = topicCidMap .asMap (). entrySet ().iterator ();
350347 while (topicCidMapIter .hasNext ()) {
351348 Map .Entry <String , ConcurrentHashMap <String , Byte >> entry = topicCidMapIter .next ();
352349 String topic = entry .getKey ();
@@ -368,7 +365,7 @@ private void cleanUnusedResource() {
368365 }
369366
370367 {
371- Iterator <Map .Entry <String , ConcurrentSkipListSet <PopRequest >>> pollingMapIter = pollingMap .entrySet ().iterator ();
368+ Iterator <Map .Entry <String , ConcurrentSkipListSet <PopRequest >>> pollingMapIter = pollingMap .asMap (). entrySet ().iterator ();
372369 while (pollingMapIter .hasNext ()) {
373370 Map .Entry <String , ConcurrentSkipListSet <PopRequest >> entry = pollingMapIter .next ();
374371 if (entry .getKey () == null ) {
0 commit comments