spring-kafka多執行緒順序消費
業務場景
我們公司是做共享充電寶的業務的。有一些比較大的代理商或者ka商戶,他們需要了解到他們自己下面的商戶的訂單資料,這些訂單資料需要由我們推送給他們。
大致架構為資料部門透過canal訂閱訂單表的資料,然後推送到kafka ,我們訂閱資料部門kafka獲取到代理商下商戶的實時訂單資料再推送給代理商。比如,代理商下商戶產生了一筆訂單,整個過程會產生,訂單生成,訂單已支付,充電寶已被取走,充電寶已歸還等多種狀態的訂單訊息,我們需要實時把這些訂單訊息推送給代理商。我們的業務場景需要訊息的順序推送和多執行緒併發消費以提高效能
kafka多執行緒消費方案
消費者程式啟動多個執行緒,每個執行緒維護專屬的KafkaConsumer例項,負責完整的訊息獲取、訊息處理
流程。如下圖所示:
消費者程式使用單或多執行緒獲取訊息,同時建立多個消費執行緒執行訊息處理邏輯。獲取訊息的執行緒可以 是一個,也可以是多個,每個執行緒維護專屬的KafkaConsumer例項,處理訊息則交由特定的執行緒池來 做,從而實現訊息獲取與訊息處理的真正解耦。具體架構如下圖所示:
這兩種方案孰優孰劣呢?應該說是各有千秋。這兩種方案的優缺點,我們先來看看下面這張表格。
kafka怎麼保證順序消費
保證順序消費,需要滿足如下條件
保證相同訂單編號的訊息需要傳送到同一個分割槽。
@Configuration
public class SenderConfig {
@Value("${kafka.bootstrap-servers}")
private String bootstrapServers;
@Bean
public Map producerConfigs() {
Map props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return props;
}
@Bean
public ProducerFactory producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
@Bean
public KafkaTemplate kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
@Bean
public Sender sender() {
return new Sender();
}
}
public class Sender {
@Autowired
private KafkaTemplate kafkaTemplate;
public void send(String topic, String data) {
kafkaTemplate.send(topic, data);
}
public void send(String topic, int partition, String data) {
kafkaTemplate.send(topic, partition, data);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringKafkaApplicationTest {
private static String BATCH_TOPIC = "batch.t";
private static Integer PARTITIONS = 6;
/**
* 已支付
*/
private static Integer PAYED_STATUS = 2;
/**
* 已取走
*/
private static Integer SEND_BACK_STATUS = 3;
@Autowired
private Sender sender;
private static DelayQueue delayQueue = new DelayQueue();
@Test
public void testReceive() throws Exception {
for (int i = 1; i < 50; i++) {
Integer orderNum = 800010 + i;
Integer orderPrice = RandomUtil.randomInt(1, 20);
// 使用者支付成功,訂單狀態為支付成功
OrderDTO order = new OrderDTO(orderNum, orderPrice, PAYED_STATUS);
// 傳送支付成功訂單訊息到對應的kafka分割槽
Integer destinationPartition = orderNum % PARTITIONS;
sender.send(BATCH_TOPIC, destinationPartition, JSONUtil.toJsonStr(order));
// 建立任務放入延遲佇列(模擬使用者支付成功到取走充電寶花費的時間)
long delayTime = 200;
OrderTask orderTask = new OrderTask(delayTime, order);
delayQueue.offer(orderTask);
}
while (true) {
// 使用者取走充電寶,訂單狀態更改為 已取走
OrderTask orderTask = (OrderTask) delayQueue.take();
OrderDTO orderDTO = orderTask.getOrderDTO();
Integer destinationPartition = orderDTO.getOrderNum() % PARTITIONS;
orderDTO.setOrderStatus(SEND_BACK_STATUS);
// 傳送已取走訂單訊息到對應的kafka 分割槽
sender.send(BATCH_TOPIC, destinationPartition, JSONUtil.toJsonStr(orderDTO));
}
}
}
可以看出我們透過訂單號對分割槽數進行取餘,來確定該訊息傳送到哪一個分割槽,保證相同訂單號的訊息被髮送到相同的分割槽。當然也可以對字串這些進行hash ,獲得hash值來對分割槽數取餘
Integer destinationPartition=orderDTO.getOrderNum()%PARTITIONS;
保證同一個分割槽的訊息由同一個執行緒來消費。
我們的業務場景需要採用多執行緒方案一來處理我們的業務
普通方式實現方案一
public class KafkaConsumerRunner implements Runnable {
private final AtomicBoolean closed = new AtomicBoolean(false);
private final KafkaConsumer consumer;
public KafkaConsumerRunner(KafkaConsumer consumer) {
this.consumer = consumer;
}
@Override
public void run() {
try {
consumer.subscribe(Arrays.asList("topic"));
while (!closed.get()) {
// 執行訊息處理邏輯
ConsumerRecords records = consumer.poll(10000);
}
} catch (Exception e) {
// Ignore exception if closing
if (!closed.get()) {
throw e;
}
} finally {
consumer.close();
}
}
/**
* Shutdown hook which can be called from a separate thread
*/
public void shutdown() {
closed.set(true);
consumer.wakeup();
}
}
spring-kafka為我們做的封裝
消費者相關配置:
這裡我們需要注意的是factory.setConcurrency(4)。
這個是配置主要是設定KafkaConsumer的數量,最大為topic 的分割槽數。當然你如果設定的值超過topic 分割槽數,spring-kafka 還是隻會為我們建立最大分割槽數的KafkaConsumer數量,也就是建立KafkaConsumer數量能少於分割槽數,但不會超過分割槽數。少於分割槽數的話,一個KafkaConsumer會消費多個分割槽的資料,保證所有的分割槽資料都有對應的KafkaConsumer來進行消費;但不會出現多個KafkaConsumer消費同一個分割槽的情況,因為如果是這樣也就無法保證訊息的順序消費機制。
一般情況下如果資料量較大,我們需要把此值設定為topic分割槽數,這樣一個KafkaConsumer消費一個分割槽的資料,提高資料的併發消費能力。
@Configuration
@EnableKafka
public class ReceiverConfig {
@Value("${kafka.bootstrap-servers}")
private String bootstrapServers;
@Bean
public Map consumerConfigs() {
Map props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.GROUP_ID_CONFIG, "batch");
// maximum records per poll
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, "100");
return props;
}
@Bean
public ConsumerFactory consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}
@Bean(name = "kafkaListenerContainerFactory")
public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
// enable batch listening
factory.setBatchListener(true);
factory.setConcurrency(4);
return factory;
}
@Bean
public Receiver receiver() {
return new Receiver();
}
}
Receiver 程式碼
public class Receiver {
@Autowired
private PushOrderService pushOrderService;
private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);
private static final String BATCH_TOPIC = "batch.t";
@KafkaListener(topics = BATCH_TOPIC, containerFactory = "kafkaListenerContainerFactory")
public void receivePartitions(List data,
@Header(KafkaHeaders.RECEIVED_PARTITION_ID) List partitions,
@Header(KafkaHeaders.OFFSET) List offsets) {
for (int i = 0; i < data.size(); i++) {
Long threadId = Thread.currentThread().getId();
// 向第三方推送訂單訊息
String orderStr = data.get(i);
pushOrderService.pushOrderToPlatform(orderStr);
OrderDTO orderDTO = JSONUtil.toBean(orderStr, OrderDTO.class);
LOGGER.info("推送訂單訊息成功,訂單號為:{},狀態為:{},分割槽為{},處理執行緒為:{}", orderDTO.getOrderNum(), orderDTO.getOrderStatus(), partitions.get(i), threadId);
}
}
}
/**
* 模擬網路推送訂單資訊給第三方平臺
*/
@Service
public class PushOrderService {
/**
* 已支付
*/
private static Integer PAYED_STATUS = 2;
public void pushOrderToPlatform(String orderString) {
// 模擬網路推送訂單資訊給第三方平臺(同步推送)
OrderDTO orderDTO = JSONUtil.toBean(orderString, OrderDTO.class);
// 已支付 訂單訊息
if (orderDTO.getOrderStatus().equals(PAYED_STATUS)) {
ThreadUtil.sleep(500);
} else {
// 已取走 訂單訊息
ThreadUtil.sleep(200);
}
}
}
測試結果: 無錫做人流手術多少錢
16:17:47.026 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800014,狀態為:2,分割槽為4,處理執行緒為:67
16:17:47.026 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800012,狀態為:2,分割槽為2,處理執行緒為:66
16:17:47.534 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800020,狀態為:2,分割槽為4,處理執行緒為:67
16:17:47.534 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800018,狀態為:2,分割槽為2,處理執行緒為:66
16:17:48.035 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800026,狀態為:2,分割槽為4,處理執行緒為:67
16:17:48.036 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800024,狀態為:2,分割槽為2,處理執行緒為:66
16:17:48.537 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800015,狀態為:2,分割槽為5,處理執行緒為:67
16:17:48.539 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800016,狀態為:2,分割槽為0,處理執行緒為:66
16:17:49.044 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800022,狀態為:2,分割槽為0,處理執行緒為:66
16:17:49.045 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800021,狀態為:2,分割槽為5,處理執行緒為:67
16:17:49.546 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800013,狀態為:2,分割槽為3,處理執行緒為:67
16:17:49.547 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800028,狀態為:2,分割槽為0,處理執行緒為:66
16:17:50.051 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800019,狀態為:2,分割槽為3,處理執行緒為:67
16:17:50.051 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800011,狀態為:2,分割槽為1,處理執行緒為:66
16:17:50.554 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800025,狀態為:2,分割槽為3,處理執行緒為:67
16:17:50.554 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800017,狀態為:2,分割槽為1,處理執行緒為:66
16:17:51.060 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800023,狀態為:2,分割槽為1,處理執行緒為:66
16:17:51.576 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800034,狀態為:2,分割槽為0,處理執行緒為:66
16:17:51.579 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800031,狀態為:2,分割槽為3,處理執行緒為:67
16:17:51.583 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800032,狀態為:2,分割槽為4,處理執行緒為:70
16:17:51.583 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800027,狀態為:2,分割槽為5,處理執行緒為:72
16:17:52.079 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800040,狀態為:2,分割槽為0,處理執行緒為:66
16:17:52.083 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800037,狀態為:2,分割槽為3,處理執行緒為:67
16:17:52.088 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800038,狀態為:2,分割槽為4,處理執行緒為:70
16:17:52.088 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800033,狀態為:2,分割槽為5,處理執行緒為:72
16:17:52.583 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800046,狀態為:2,分割槽為0,處理執行緒為:66
16:17:52.588 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800043,狀態為:2,分割槽為3,處理執行緒為:67
16:17:52.589 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800044,狀態為:2,分割槽為4,處理執行緒為:70
16:17:52.590 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800039,狀態為:2,分割槽為5,處理執行緒為:72
16:17:53.089 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800052,狀態為:2,分割槽為0,處理執行緒為:66
16:17:53.091 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800050,狀態為:2,分割槽為4,處理執行緒為:70
16:17:53.091 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800049,狀態為:2,分割槽為3,處理執行緒為:67
16:17:53.095 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800045,狀態為:2,分割槽為5,處理執行緒為:72
16:17:53.591 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800058,狀態為:2,分割槽為0,處理執行緒為:66
16:17:53.592 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800056,狀態為:2,分割槽為4,處理執行緒為:70
16:17:53.593 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800055,狀態為:2,分割槽為3,處理執行緒為:67
16:17:53.600 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800051,狀態為:2,分割槽為5,處理執行緒為:72
16:17:53.795 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800016,狀態為:3,分割槽為0,處理執行緒為:66
16:17:53.796 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800013,狀態為:3,分割槽為3,處理執行緒為:67
16:17:53.796 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800014,狀態為:3,分割槽為4,處理執行緒為:70
16:17:54.000 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800020,狀態為:3,分割槽為4,處理執行緒為:70
16:17:54.000 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800019,狀態為:3,分割槽為3,處理執行緒為:67
16:17:54.000 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800022,狀態為:3,分割槽為0,處理執行緒為:66
16:17:54.101 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800057,狀態為:2,分割槽為5,處理執行緒為:72
16:17:54.205 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800026,狀態為:3,分割槽為4,處理執行緒為:70
16:17:54.206 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800025,狀態為:3,分割槽為3,處理執行緒為:67
16:17:54.206 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800028,狀態為:3,分割槽為0,處理執行緒為:66
16:17:54.306 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800015,狀態為:3,分割槽為5,處理執行緒為:72
16:17:54.410 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800037,狀態為:3,分割槽為3,處理執行緒為:67
16:17:54.410 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800034,狀態為:3,分割槽為0,處理執行緒為:66
16:17:54.410 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800032,狀態為:3,分割槽為4,處理執行緒為:70
16:17:54.510 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800021,狀態為:3,分割槽為5,處理執行緒為:72
16:17:54.614 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800031,狀態為:3,分割槽為3,處理執行緒為:67
16:17:54.615 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800046,狀態為:3,分割槽為0,處理執行緒為:66
16:17:54.615 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800038,狀態為:3,分割槽為4,處理執行緒為:70
16:17:54.711 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800027,狀態為:3,分割槽為5,處理執行緒為:72
16:17:54.820 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800043,狀態為:3,分割槽為3,處理執行緒為:67
16:17:54.820 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800040,狀態為:3,分割槽為0,處理執行緒為:66
16:17:54.820 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800056,狀態為:3,分割槽為4,處理執行緒為:70
16:17:54.914 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800033,狀態為:3,分割槽為5,處理執行緒為:72
16:17:55.025 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800044,狀態為:3,分割槽為4,處理執行緒為:70
16:17:55.025 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800052,狀態為:3,分割槽為0,處理執行緒為:66
16:17:55.025 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800055,狀態為:3,分割槽為3,處理執行緒為:67
16:17:55.118 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800039,狀態為:3,分割槽為5,處理執行緒為:72
16:17:55.231 [org.springframework.kafka.KafkaListenerEndpointContainer#0-2-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800050,狀態為:3,分割槽為4,處理執行緒為:70
16:17:55.231 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800049,狀態為:3,分割槽為3,處理執行緒為:67
16:17:55.231 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800058,狀態為:3,分割槽為0,處理執行緒為:66
16:17:55.321 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800057,狀態為:3,分割槽為5,處理執行緒為:72
16:17:55.525 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800051,狀態為:3,分割槽為5,處理執行緒為:72
16:17:55.728 [org.springframework.kafka.KafkaListenerEndpointContainer#0-3-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800045,狀態為:3,分割槽為5,處理執行緒為:72
16:17:55.735 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800029,狀態為:2,分割槽為1,處理執行緒為:66
16:17:55.737 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800030,狀態為:2,分割槽為2,處理執行緒為:67
16:17:56.239 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800036,狀態為:2,分割槽為2,處理執行緒為:67
16:17:56.239 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800035,狀態為:2,分割槽為1,處理執行緒為:66
16:17:56.743 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800042,狀態為:2,分割槽為2,處理執行緒為:67
16:17:56.743 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800041,狀態為:2,分割槽為1,處理執行緒為:66
16:17:57.247 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800047,狀態為:2,分割槽為1,處理執行緒為:66
16:17:57.247 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800048,狀態為:2,分割槽為2,處理執行緒為:67
16:17:57.751 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800053,狀態為:2,分割槽為1,處理執行緒為:66
16:17:57.751 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800054,狀態為:2,分割槽為2,處理執行緒為:67
16:17:57.953 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800012,狀態為:3,分割槽為2,處理執行緒為:67
16:17:58.159 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800018,狀態為:3,分割槽為2,處理執行緒為:67
16:17:58.256 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800059,狀態為:2,分割槽為1,處理執行緒為:66
16:17:58.361 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800024,狀態為:3,分割槽為2,處理執行緒為:67
16:17:58.457 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800011,狀態為:3,分割槽為1,處理執行緒為:66
16:17:58.566 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800048,狀態為:3,分割槽為2,處理執行緒為:67
16:17:58.662 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800017,狀態為:3,分割槽為1,處理執行緒為:66
16:17:58.771 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800042,狀態為:3,分割槽為2,處理執行緒為:67
16:17:58.868 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800023,狀態為:3,分割槽為1,處理執行緒為:66
16:17:58.975 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800030,狀態為:3,分割槽為2,處理執行緒為:67
16:17:59.073 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800029,狀態為:3,分割槽為1,處理執行緒為:66
16:17:59.177 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800036,狀態為:3,分割槽為2,處理執行緒為:67
16:17:59.279 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800041,狀態為:3,分割槽為1,處理執行緒為:66
16:17:59.383 [org.springframework.kafka.KafkaListenerEndpointContainer#0-1-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800054,狀態為:3,分割槽為2,處理執行緒為:67
16:17:59.481 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800035,狀態為:3,分割槽為1,處理執行緒為:66
16:17:59.685 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800053,狀態為:3,分割槽為1,處理執行緒為:66
16:17:59.891 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800047,狀態為:3,分割槽為1,處理執行緒為:66
16:18:00.092 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1] INFO c.c.kafka.consumer.Receiver - 推送訂單訊息成功,訂單號為:800059,狀態為:3,分割槽為1,處理執行緒為:66
完整程式碼
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2659344/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- kafka多執行緒順序消費Kafka執行緒
- Linux c多執行緒執行順序Linux執行緒
- Java多執行緒消費訊息Java執行緒
- Python執行緒專題10:queue、多執行緒按順序執行Python執行緒
- 多執行緒實現順序迴圈列印執行緒
- 多優先順序執行緒池實踐執行緒
- RabbitMQ多消費者順序性消費訊息實現MQ
- 使用多執行緒增加kafka消費能力執行緒Kafka
- Java 多執行緒基礎(十一)執行緒優先順序和守護執行緒Java執行緒
- 【java】【多執行緒】睡眠/守護/加入/禮讓執行緒,執行緒優先順序(4)Java執行緒
- 執行緒執行順序——CountDownLatch、CyclicBarrier 、join()、執行緒池執行緒CountDownLatch
- 多執行緒-執行緒排程及獲取和設定執行緒優先順序執行緒
- java多執行緒之消費生產模型Java執行緒模型
- 多執行緒之生產者消費者執行緒
- java執行緒優先順序Java執行緒
- 程式設計思想之多執行緒與多程式(2):執行緒優先順序與執行緒安全程式設計執行緒
- java多執行緒:執行緒間通訊——生產者消費者模型Java執行緒模型
- Java多執行緒——生產者消費者示例Java執行緒
- disruptor中多執行緒消費者的疑問執行緒
- RocketMQ系列(四)順序消費MQ
- RocketMQ(7)---RocketMQ順序消費MQ
- 警惕執行緒的優先順序執行緒
- Java中如何保證執行緒順序執行Java執行緒
- Java 多執行緒學習(執行緒通訊——消費者和生產者)Java執行緒
- Java多執行緒——生產者和消費者模式Java執行緒模式
- Java多執行緒14:生產者/消費者模型Java執行緒模型
- 利用訊號量實現執行緒順序執行執行緒
- Java之執行緒的優先順序Java執行緒
- 如何使用ReentrantLock的條件變數,讓多個執行緒順序執行?ReentrantLock變數執行緒
- Java 多執行緒(Java.Thread)------ 執行緒協作(生產者消費者模式)Java執行緒thread模式
- 【高併發】深入理解執行緒的執行順序執行緒
- Swift多執行緒之Operation:按優先順序載入圖片Swift執行緒
- 令人費解的 async/await 執行順序AI
- Java 多執行緒基礎(十二)生產者與消費者Java執行緒
- Java多執行緒——消費者與生產者的關係Java執行緒
- Python-多執行緒及生產者與消費者Python執行緒
- python中多執行緒消費者生產者問題Python執行緒
- 多執行緒-生產者消費者問題程式碼1執行緒