Java系統(tǒng)中拆分同步和異步詳解
前言
很多開(kāi)發(fā)人員說(shuō),將應(yīng)用程序切換到異步處理很復(fù)雜。因?yàn)樗麄冇幸粋€(gè)天然需要同步通信的Web應(yīng)用程序。在這篇文章中,我想介紹一種方法來(lái)達(dá)到異步通信的目的:使用一些眾所周知的庫(kù)和工具來(lái)設(shè)計(jì)他們的系統(tǒng)。 下面的例子是用Java編寫(xiě)的,但我相信它更多的是基本原理,同一個(gè)應(yīng)用程序可以用任何語(yǔ)言來(lái)重新寫(xiě)。
所需的工具和庫(kù):
- Spring Boot
- RabbitMQ
1.Web應(yīng)用程序
一個(gè)用Spring MVC編寫(xiě)的Web應(yīng)用程序并運(yùn)行在Tomcat上。 它所做的只是將一個(gè)字符串發(fā)送到一個(gè)隊(duì)列中 (異步通信的開(kāi)始) 并等待另一個(gè)隊(duì)列中的消息作為HTTP響應(yīng)發(fā)送回來(lái)。
首先,我們需要定義幾個(gè)依賴項(xiàng),然后等待Spring Boot執(zhí)行所有必要的自動(dòng)配置。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>com.thedeanda</groupId>
<artifactId>lorem</artifactId>
</dependency>
</dependencies>
@SpringBootApplication
public class BlockingApplication {
public static void main(String[] args) {
SpringApplication.run(BlockingApplication.class, args);
}
@RestController
public static class MessageController {
private final RabbitTemplate rabbitTemplate;
public MessageController(CachingConnectionFactory connectionFactory) {
this.rabbitTemplate = new RabbitTemplate(connectionFactory);
}
@GetMapping("invoke")
public String sendMessage() {
Message response = rabbitTemplate.sendAndReceive("uppercase", null, request());
return new String(response.getBody());
}
private static Message request() {
Lorem LOREM = LoremIpsum.getInstance();
String name = LOREM.getFirstName() + " " + LOREM.getLastName();
return new Message(name.getBytes(), new MessageProperties());
}
}
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setAddresses("localhost:5672");
factory.setUsername("admin");
factory.setPassword("admin");
return factory;
}
}
2.消費(fèi)端應(yīng)用程序
第二個(gè)應(yīng)用程序僅僅是一個(gè)等待消息的RabbitMQ的消費(fèi)端,將拿到的字符串轉(zhuǎn)換為大寫(xiě),然后將此結(jié)果發(fā)送到輸出隊(duì)列中。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
@SpringBootApplication
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
public static class MessageListener {
public String handleMessage(byte[] message) {
Random rand = new Random();
// Obtain a number between [0 - 49] + 50 = [50 - 99]
int n = rand.nextInt(50) + 50;
String content = new String(message);
try {
Thread.sleep(n);
} catch (InterruptedException e) {
e.printStackTrace();
}
return content.toUpperCase();
}
}
@Bean
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setAddresses("localhost:5672");
factory.setUsername("admin");
factory.setPassword("admin");
return factory;
}
@Bean
public SimpleMessageListenerContainer serviceListenerContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setConcurrentConsumers(20);
container.setMaxConcurrentConsumers(40);
container.setQueueNames("uppercase_messages");
container.setMessageListener(new MessageListenerAdapter(new MessageListener()));
return container;
}
}
3.底層如何執(zhí)行的?
程序啟動(dòng)并首次調(diào)用sendMessage()方法后,我們可以看到Spring AMQP支持自動(dòng)創(chuàng)建了一個(gè)新的回復(fù)隊(duì)列并等待來(lái)自我們的服務(wù)應(yīng)用程序的響應(yīng)。
2019-05-12 17:23:21.451 INFO 4574 --- [nio-8080-exec-1] .l.DirectReplyToMessageListenerContainer : Container initialized for queues: [amq.rabbitmq.reply-to]
2019-05-12 17:23:21.457 INFO 4574 --- [nio-8080-exec-1] .l.DirectReplyToMessageListenerContainer : SimpleConsumer [queue=amq.rabbitmq.reply-to, consumerTag=amq.ctag-VF-iqD9rLEuljIBstbCI1A identity=10e58093] started
如果我們?cè)谙M(fèi)端應(yīng)用程序中查看消息,我們可以看到Spring自動(dòng)傳播有關(guān)回復(fù)隊(duì)列的信息以及**相關(guān)ID,**用于將其傳遞回Web應(yīng)用程序以便能夠?qū)⒄?qǐng)求和響應(yīng)配對(duì)在一起。
這就是發(fā)生魔術(shù)的地方。 當(dāng)然,如果您想使其更復(fù)雜,您可以在協(xié)作中包含更多服務(wù),然后將Web應(yīng)用程序的最終響應(yīng)放入與自動(dòng)生成的隊(duì)列不同的隊(duì)列中, 該隊(duì)列只具有正確的關(guān)聯(lián)ID。 另外,不要忘記設(shè)置合理的超時(shí)。
這個(gè)解決方案還有一個(gè)很大的缺點(diǎn) - 應(yīng)用程序吞吐量。 我故意這樣做,以便我可以跟進(jìn)這篇文章,進(jìn)一步深入調(diào)查AsyncProfiler! 但是目前,我們使用Tomcat作為主HTTP服務(wù)器,默認(rèn)為200個(gè)線程,這意味著我們的應(yīng)用程序無(wú)法同時(shí)處理200多條消息,因?yàn)槲覀兊姆?wù)器線程正在等待RabbitMQ 回復(fù)隊(duì)列的響應(yīng),直到有消息進(jìn)入或發(fā)生超時(shí)。
感謝您閱讀本文,敬請(qǐng)關(guān)注后續(xù)內(nèi)容! 如果您想自己嘗試一下,請(qǐng)查看我的GitHub存儲(chǔ)庫(kù)。
原文鏈接:dzone.com/articles/ho…
作者:Petr Bouda
譯者:KeepGoingPawn
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
關(guān)于@OnetoMany關(guān)系映射的排序問(wèn)題,使用注解@OrderBy
這篇文章主要介紹了關(guān)于@OnetoMany關(guān)系映射的排序問(wèn)題,使用注解@OrderBy,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
springcloud?gateway實(shí)現(xiàn)簡(jiǎn)易版灰度路由步驟詳解
這篇文章主要為大家介紹了springcloud?gateway實(shí)現(xiàn)簡(jiǎn)易版灰度路由步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
Spring Bean生命周期之Bean的實(shí)例化詳解
這篇文章主要為大家詳細(xì)介紹了Spring Bean生命周期之Bean的實(shí)例化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
基于JPA實(shí)體類(lèi)監(jiān)聽(tīng)器@EntityListeners注解的使用實(shí)例
這篇文章主要介紹了JPA實(shí)體類(lèi)監(jiān)聽(tīng)器@EntityListeners注解的使用實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
MyBatis-Plus動(dòng)態(tài)返回實(shí)體類(lèi)示例詳解
這篇文章主要為大家介紹了MyBatis-Plus動(dòng)態(tài)返回實(shí)體類(lèi)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Java BufferedWriter BufferedReader 源碼分析
本文是關(guān)于Java BufferedWriter ,BufferedReader 簡(jiǎn)介、分析源碼 對(duì)Java IO 流深入了解,希望看到的同學(xué)對(duì)你有所幫助2016-07-07
劍指Offer之Java算法習(xí)題精講二叉搜索樹(shù)與數(shù)組查找
跟著思路走,之后從簡(jiǎn)單題入手,反復(fù)去看,做過(guò)之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化2022-03-03
SpringBoot+ShardingSphereJDBC實(shí)現(xiàn)讀寫(xiě)分離詳情
這篇文章主要介紹了SpringBoot+ShardingSphereJDBC實(shí)現(xiàn)讀寫(xiě)分離詳情,通過(guò)用??MySQL??進(jìn)行一主一從的主從復(fù)制展開(kāi)全文內(nèi)容,需要的朋友可以參考一下2022-08-08

