很多开发人员说,将应用程序切换到异步处理很复杂。因为他们有一个天然需要同步通信的Web应用程序。在这篇文章中,我想介绍一种方法来达到异步通信的目的:使用一些众所周知的库和工具来设计他们的系统。 下面的例子是用Java编写的,但我相信它更多的是基本原理,同一个应用程序可以用任何语言来重新写。

所需的工具和库:

Spring Boot

RabbitMQ

1.Web应用程序

一个用Spring MVC编写的Web应用程序并运行在Tomcat上。 它所做的只是将一个字符串发送到一个队列中 (异步通信的开始) 并等待另一个队列中的消息作为HTTP响应发送回来。

首先,我们需要定义几个依赖项,然后等待Spring Boot执行所有必要的自动配置。

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-amqp

com.thedeanda

lorem

@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.消费端应用程序

第二个应用程序仅仅是一个等待消息的RabbitMQ的消费端,将拿到的字符串转换为大写,然后将此结果发送到输出队列中。

org.springframework.boot

spring-boot-starter-amqp

@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.底层如何执行的?

程序启动并首次调用sendMessage()方法后,我们可以看到Spring AMQP支持自动创建了一个新的回复队列并等待来自我们的服务应用程序的响应。

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

如果我们在消费端应用程序中查看消息,我们可以看到Spring自动传播有关回复队列的信息以及**相关ID,**用于将其传递回Web应用程序以便能够将请求和响应配对在一起。

这就是发生魔术的地方。 当然,如果您想使其更复杂,您可以在协作中包含更多服务,然后将Web应用程序的最终响应放入与自动生成的队列不同的队列中, 该队列只具有正确的关联ID。 另外,不要忘记设置合理的超时。

这个解决方案还有一个很大的缺点 - 应用程序吞吐量。 我故意这样做,以便我可以跟进这篇文章,进一步深入调查AsyncProfiler! 但是目前,我们使用Tomcat作为主HTTP服务器,默认为200个线程,这意味着我们的应用程序无法同时处理200多条消息,因为我们的服务器线程正在等待RabbitMQ 回复队列的响应,直到有消息进入或发生超时。

感谢您阅读本文,敬请关注后续内容! 如果您想自己尝试一下,请查看我的GitHub存储库。

很多开发人员说,将应用程序切换到异步处理很复杂。因为他们有一个天然需要同步通信的Web应用程序。在这篇文章中,我想介绍一种方法来达到异步通信的目的:使用一些众所周知的库和工具来设计他们的系统。 下面的例子是用Java编写的,但我相信它更多的是基本原理,同一个应用程序可以用任何语言来重新写。

所需的工具和库:

- Spring Boot- RabbitMQ

## 1.Web应用程序

一个用Spring MVC编写的Web应用程序并运行在Tomcat上。 它所做的只是将一个字符串发送到一个队列中 (异步通信的开始) 并等待另一个队列中的消息作为HTTP响应发送回来。

首先,我们需要定义几个依赖项,然后等待Spring Boot执行所有必要的自动配置。

```java            org.springframework.boot        spring-boot-starter-web                org.springframework.boot        spring-boot-starter-amqp                com.thedeanda        lorem    ```

```java@SpringBootApplicationpublic 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.消费端应用程序

第二个应用程序仅仅是一个等待消息的RabbitMQ的消费端,将拿到的字符串转换为大写,然后将此结果发送到输出队列中。

```java            org.springframework.boot        spring-boot-starter-amqp    ```

```java@SpringBootApplicationpublic 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.底层如何执行的?

程序启动并首次调用sendMessage()方法后,我们可以看到Spring AMQP支持自动创建了一个新的**回复队列**并等待来自我们的服务应用程序的响应。

```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```

如果我们在消费端应用程序中查看消息,我们可以看到Spring自动传播有关**回复队列**的信息以及**相关ID,**用于将其传递回Web应用程序以便能够将请求和响应配对在一起。

这就是发生魔术的地方。 当然,如果您想使其更复杂,您可以在协作中包含更多服务,然后将Web应用程序的最终响应放入与自动生成的队列不同的队列中, 该队列只具有正确的*关联ID*。 另外,不要忘记设置合理的超时。

这个解决方案还有一个很大的缺点 - 应用程序吞吐量。 我故意这样做,以便我可以跟进这篇文章,进一步深入调查`AsyncProfiler`! 但是目前,我们使用Tomcat作为主HTTP服务器,默认为200个线程,这意味着我们的应用程序无法同时处理200多条消息,因为我们的服务器线程正在等待RabbitMQ **回复队列**的响应,直到有消息进入或发生超时。

感谢您阅读本文,敬请关注后续内容! 如果您想自己尝试一下,请查看我的[GitHub存储库](https://github.com/petrbouda/rabbitmq-async-microservices)。

> 原文链接:https://dzone.com/articles/how-to-split-up-a-synchronous-and-asynchronous-of

> [作者:Petr Bouda](https://github.com/petrbouda)

> [译者:KeepGoingPawn](https://github.com/KeepGoingPawn)

java web系统拆分_Java系统中如何拆分同步和异步相关推荐

  1. 基于Java Web的在线考试系统的实现

    摘  要 随着互联网的发展,教育的方式逐渐步入信息化.智能化,网络教育逐渐成为教育未来发展的重要趋势,在线考试系统成为教育成果考察的主流方向.在线考试充分利用现代信息化技术的优势,使考试更方便.更高效 ...

  2. 毕业设计 - 基于java web的在线考试系统【源码+论文】

    文章目录 前言 一.项目设计 1. 模块设计 2. 基本功能 2.1 登录功能 2.2 系统答题 2.3 答题得分 2.4 错题解析 3. 实现效果 二.部分源码 项目源码 前言 今天学长向大家分享一 ...

  3. 基于java web的在线考试系统(源码+论文)

    今天介绍的一个项目是, 基于java web的在线考试系统 1 设计内容及要求 1.1 在线考试系统概述 基于Java web开发的在线考试系统不仅可以充分利用校园内各种资源,对学校的各种教学资源进行 ...

  4. 基于Java Web的汽车租赁系统的设计与实现

    项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等.这里根据疫情当下,你 ...

  5. 计算机毕业设计 java web网上购物商城系统(源码+论文)

    文章目录 0 项目说明 1 系统设计 2 数据库设计 2.1 实体属性的定义 3 界面展示 4 论文概览 5 项目源码 0 项目说明 java web网上购物商城系统 提示:适合用于课程设计或毕业设计 ...

  6. 【毕业设计/课程设计】java web网上购物商城系统(源码+论文)

    文章目录 0 项目说明 1 系统设计 2 数据库设计 2.1 实体属性的定义 3 界面展示 4 论文概览 5 项目源码 0 项目说明 java web网上购物商城系统 提示:适合用于课程设计或毕业设计 ...

  7. 基于java web的网上书店系统

    006基于java web的网上书店系统(含论文) 开发环境: Eclipse/MyEclipse.Tomcat8.Jdk1.8 数据库: MySQL 适用于: 课程设计,毕业设计,学习等等 系统介绍 ...

  8. 基于Java web的大学生就业系统

    基于Java web的大学生就业系统 技术点: java+hibernate+struts+jspeclipse+mysql+tomcat 1.主界面 2.公告信息 3.招聘信息 4.管理员功能 5. ...

  9. 毕业设计 基于java web的网上招标系统

    文章目录 前言 一.项目设计 1. 模块设计 注册用户部分 管理员部分 2. 实现效果 二.部分源码 最后 前言 今天学长向大家分享一个 毕业设计项目: 基于java web的网上招标系统 一.项目设 ...

  10. python同步异步_python中Tornado的同步与异步I/O的介绍(附示例)

    本篇文章给大家带来的内容是关于python中Tornado的同步与异步I/O的介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 协程是Tornado种推荐的编程方式,使用 ...

最新文章

  1. BZOJ1296:[SCOI2009]粉刷匠
  2. SQL的事务回滚操作带案例分析
  3. [转]jquery的一个模板引擎-zt
  4. 为什么我们总是「习惯性辩解」?
  5. Myesclipe+SSH+jsp+mysql+tomcate实现一个简单的CRM客户关系管理系统
  6. 前端学习(2785):实现导航的基本结构
  7. golang学习之旅(1)
  8. 李宏毅老师ML_HW1——PM2.5预测
  9. 优秀的程序员都避开了哪些坑?
  10. Parencodings 模拟
  11. Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
  12. 【回文串1 动态规划 马拉车算法】LeetCode 5. Longest Palindromic Substring
  13. 各银行支付/各种支付平台/php对接支付接口心得/php h5支付接口对接
  14. 知识图谱从0到-1的笔记——6.知识推理
  15. 永远的Beyond, 永远的家驹
  16. 终于得空,写两句了......
  17. 25W三星快充协议芯片,支持支持USB PD 3.0
  18. android百度天气接口api接口,百度天气接口api
  19. JAVA中将html转换成pdf
  20. 用GPIO模拟SPI接口读取传感器数据

热门文章

  1. 洛谷 P1003 铺地毯
  2. iOS开发——NSArray中的字典排序
  3. unity, standard shader消耗两个draw call
  4. MySql 几个命令
  5. 毕业以来,今天第一次领到工资,好兴奋哪
  6. oracle12c em 空白,Oracle12C 开启关闭em
  7. 082_html5Web存储
  8. dir在python中什么意思_python中dir是什么
  9. csrf防御 java_一分钟了解【CSRF攻击与防御】
  10. python中使用函数的优点_Python基础之函数基本用法与进阶详解