1. What is middleware
What is middleware
Since the 1980s, Chinese enterprises have gradually carried out information construction. Due to the immature methods and systems and the changing market demand of enterprise business, an enterprise may run multiple different business systems at the same time. These systems may be based on different operating systems, different databases and heterogeneous network environment. The problem now is how to combine these information systems into an organic collaborative whole to truly realize enterprise cross platform and distributed applications. Middleware is the solution. It trades its complexity for the simplicity of enterprise applications.
Middleware is software between operating system and application program. Some people think it should be a part of operating system. When using middleware, people often integrate a group of middleware to form a platform (including development platform and operation platform), but there must be a communication middleware in this group of middleware, that is, middleware + platform + communication. This definition also limits that it can be called middleware only when used in distributed systems, At the same time, it can be distinguished from supporting software and using software
Why use message oriented middleware
Specifically, middleware shields the complexity of the underlying operating system, makes program developers face a simple and unified development environment, reduces the complexity of program design, focuses on their own business, and does not have to work repeatedly for the migration of programs on different system software, which greatly reduces the technical burden. Middleware brings to the application system, Not only the simplicity of development and the shortening of development cycle, but also the workload of system maintenance, operation and management, but also the investment of overall computer cost.
Middleware features
In order to solve the problem of distributed heterogeneity, the concept of middleware is proposed. Middleware is a general service between platforms (hardware and operating system) and applications. As shown in the figure below, these services have standard program interfaces and protocols. For different operating systems and hardware platforms, they can have a variety of implementations that meet the protocol specifications of interfaces.
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-oL84NlWR-1633954870580)(image/1.jpg)]
It is also difficult to give a strict definition to middleware, but middleware should have the following characteristics:
(1) Meet the needs of a large number of applications
(2) Runs on a variety of hardware and OS platforms
(3) Support distributed computing and provide transparent interaction of applications or services across networks, hardware and OS platforms
(4) Support standard protocols
(5) Support standard interfaces
Due to the importance of standard interfaces for portability and standard protocols for interoperability, middleware has become the main part of many standardization work. For application software development, middleware is far more important than operating system and network services. The program interface provided by middleware defines a relatively stable high-level application environment, regardless of the underlying computer hardware and system software As long as the middleware is upgraded and the external interface definition of the middleware remains unchanged, the application software hardly needs any modification, so as to protect the significant investment of enterprises in the development and maintenance of application software.
To put it simply: middleware has a great feature. It is separated from the specific design objectives and has modules that provide universal independent functional requirements. This makes the middleware must be replaceable. If the middleware is irreplaceable in a system design, and there is no problem with the architecture and framework design, it is the middleware. It may be a middleware elsewhere in this system Inside is the engine.
When will middleware technology be used in the project
In the architecture and reconstruction of the project, we need to carefully consider and think about the use of any technology and architecture change, because the integration and change of any technology may increase personnel, technology and cost. Middleware technology is generally used more in some Internet companies or projects. If you are only a start-up company, it is recommended to use a single architecture At most, add a cache middleware. Don't blindly pursue new or so-called high performance. Behind the pursuit must be the business driver and project driver, because once the pursuit means that your learning cost, the company's personnel structure, server cost, maintenance and operation and maintenance cost will increase, so you need to choose and consider carefully.
However, as an open person, you must have the ability and thinking to learn middleware technology. Otherwise, it is easy to master estimation or mention it in the interview when the project develops to a stage, which will bring you a lot of trouble. In today's era, these technologies are not new. If you master and mine, the key is to spend your time and experience Through discussion and research.
2. Overview of middleware technology and architecture
Learn the ways and skills of Middleware
- Understand the role of Middleware in the project architecture and the underlying implementation of each middleware
- Some analogical life concepts can be used to understand middleware
- Use some flow charts or brain maps to sort out the role of various middleware in the architecture
- Try to use java technology to realize the principle of middleware
- Calm down and think about the reasons for the design and use of Middleware in the project
- If the corresponding alternative summary scheme is found
- Try to write a blog to summarize the comparison and use scenarios of similar middleware technologies
- Learn to view the source code of middleware, open source projects and blogs
What is message oriented middleware
In the actual project, most enterprise project development adopts the single architecture mode in the early morning
Monomer architecture
In enterprise development, most of the initial architectures adopt the mode of single architecture, and the typical feature of this architecture is to put all businesses and modules, source code, static resource files, etc. in one project. If a module is upgraded or iterated, the project will be recompiled and redeployed The problems with this dog are:
- Coupling too high
- Difficult to maintain
- High cost of server
- And the complexity of upgrading the architecture will also increase
In this way, there will be subsequent distributed architecture systems, as follows
Distributed architecture
What is a distributed system
More popular: a request is completed by multiple services (services or systems) on the server side
Different from the single architecture, the single architecture is that a request initiates a jvm scheduling Thread (specifically, tomcat Thread pool) to allocate a Thread thread Thread to process the request until it is released, while the distributed system is that multiple systems cooperate to complete a request, and the jvm and environment can be independent. If it is a metaphor in life, the single structure is like building a small house, which can be completed soon. If you want to build a bird's nest or a large building, you must coordinate and distribute all links. This purpose is also a problem to be deployed and considered when the project develops to the later stage. It is not difficult to see that the characteristics and problems of distributed architecture system are as follows:
Problems:
- High learning cost and too many technology stacks
- Increased operation and maintenance costs and server costs
- The cost of personnel will also increase
- The load of the project will also increase
- The number of errors and fault tolerance will also multiply
- The choice of occupied server port and communication cost is high
- Security considerations and factors force you to choose RMI/MQ related server-side communication
Benefits:
- The independence of the service system reduces the server resources occupied and the hardware cost occupied. To be exact, the service resources can be reasonably allocated
- Source, no waste of server resources
- Independent maintenance and deployment of the system, reduced coupling and pluggability
- The choice of system architecture and technology stack can become flexible (rather than simply choosing java)
- Flexible deployment will not cause the platform to be paralyzed or out of service due to deployment
3. Architecture of distributed system based on Message Oriented Middleware)
As can be seen from the above figure, the of message oriented middleware is
- Use reliable message passing mechanism for direct communication between the system and the system
- By providing message passing and message party mechanism, it can expand the communication between processes in the distributed system environment
Scenario of message oriented middleware application
- Cross system data transfer
- High concurrent traffic peak clipping
- Concurrent and asynchronous processing of data
- Big data analysis and transmission
- Distributed transactions, such as when you have a data to migrate or too many concurrent requests,
For example, if you have 10 W concurrent requests to place orders, we can stack the order requests into the message queue before these orders are warehoused, so that they can be warehoused and executed stably and reliably
Common message oriented middleware
ActiveMQ, RabbitMQ, Kafka, RocketMQ, etc
The essence and design of Message Oriented Middleware
It is a technical service with the functions of receiving data, receiving requests, storing data, sending data and so on
MQ message queue: it is responsible for data transmission, reception, storage and transmission, so its performance is higher than that of ordinary services and technologies
Who will produce, store and consume messages?
The core component of Message Oriented Middleware
Message protocol
Message persistence mechanism
Message distribution policy
High availability and reliability of messages
Fault tolerance mechanism of message
Summary
In fact, whether you choose single architecture or distributed architecture is a stage of project development. At what stage, you should choose the appropriate architecture instead of blindly pursuing it. The final consequences and problems need to pay for themselves. But as a developer, learning and exploring new technologies makes it a problem that every program developer should keep and think about. When we can't change the society and the world, in order to live and survive, we must meet the needs of enterprises and the market, give full play to your value and learned talents, create value and realize ourselves
4. Message queuing protocol
What is an agreement
The so-called agreement means:
- A set of conventions that the underlying operating system and application program of a computer follow when communicating. Only by following the common conventions and specifications can the system and the underlying operating system communicate with each other
- Different from general network applications, it is mainly responsible for data acceptance and transmission, so its performance is relatively high
- The protocol must strictly abide by the specifications for data format and data exchange between computers
Three elements of network protocol
- Syntax: syntax is the structure and format of user data and control information, as well as the order in which data appears
- Semantics: semantics is to explain the meaning of each part of the control information. It specifies what control information needs to be sent, what actions to be completed and what responses to be made
- Timing: timing is a detailed description of the sequence of events
For example, I send a message to the queue in what data format, and then what is the meaning of each part, the actions executed after sending, the actions of consumer consumption messages, and the corresponding structure and feedback after consumption, and then process it according to the corresponding execution order. If you still don't understand the http request protocol that everyone contacts every day:
- Syntax: http specifies the format of request message and response message
- Semantics: a request initiated by a client is called a request (this is a definition, and you initiate a post/get request)
- Timing: a request corresponds to a response (there must be a request before there is a response. This is timing)
The message middleware does not use http protocol, but the common message middleware protocols are: OpenWire, AMQP, MQTT, Kafka and OpenMessage protocol
Interview question: why does message oriented middleware not directly use http protocol
- Because the http request message header and response message header are relatively complex, including cookies, data encryption and decryption, windowsill, response code and other additional functions. However, for a message, we do not need to be so complex or necessary. It is actually responsible for data transmission, storage and distribution. We must pursue high performance. Try to be concise and fast
- In most cases, http is mostly short links. In the actual interaction process, a request to response is likely to be interrupted. After the interruption, persistence will not be executed, which will cause the loss of requests. This is not conducive to the business scenario of message middleware, because message middleware may be a long-term process of obtaining information. In case of problems and faults, it is necessary to persist the data or messages in order to ensure the highly reliable and stable operation of messages and data
AMQP protocol
AMQP: (full name: Advanced Message Queuing Protocol) is an Advanced Message Queuing Protocol. Jointly designed by JPMorgan Chase group and other companies. It is an application layer standard high-level message queuing protocol that provides unified messaging services. It is an open standard of application layer protocol. It is designed for message oriented middleware. The client and message middleware based on this protocol can deliver messages, which is not limited by different products and different development languages of the client / middleware. The implementation in Erlang is implemented by RabbitMQ et al
characteristic:
- Distributed transaction support
- Message persistence support
- High performance and reliable message processing advantages
MQTT protocol
MQTT protocol (message queuing Telecommunication Transport) message queue is an open real-time communication protocol of IBM and an important part of the system architecture of the Internet of things
characteristic:
- Light weight
- Simple structure
- Fast transmission, transaction not supported
- No persistence design
Application scenario:
- Applicable to limited computing power
- Low bandwidth
- Scenario of network instability
supporter:
OpenMessage protocol
It is an application development standard in the fields of Distributed Information Middleware and stream processing jointly founded by Alibaba, Yahoo, Didi travel, Stremalio and other companies in recent years
characteristic:
- Simple structure
- Fast parsing speed
- Support transaction and persistence design
Kafka protocol
Kafka protocol is a binary protocol based on TCP/IP. The message is divided by length and consists of some basic data types
characteristic:
- Simple structure
- Fast parsing speed
- No transaction support
- Persistent design
Summary
Protocol: a protocol, commonly known as the specification and mechanism, built on the basis of tcp/ip protocol. Its main purpose is to enable the client (application java, go) to communicate and communicate. And this specification must have persistence, high availability and high reliability
5. Message queue persistence
Persistence
Simply put, it is to store the data on disk instead of in memory. It will disappear when the server is restarted and disconnected, so that the data can be saved permanently
Common persistence methods
Files and databases (rabbitmq), the rest are files
6. Message distribution strategy
Message distribution policy
MQ message queuing has the following roles
- producer
- Store message
- consumer
After the producer generates the message, MQ stores it. How does the consumer get the message? Generally, there are two ways to obtain data: push or pull. A typical git has a push-pull mechanism. The http request we send is a typical process of pulling database data back. Message queue MQ is a push process, and these push mechanisms will use many business scenarios and have many corresponding push mechanism policies
Scenario analysis I
There are many systems and services. How do we know which system or server or system consumes this message? At this time, we need a distribution strategy. This requires a consumption strategy. Or call it the methodology of consumption
Scenario analysis II
In the process of sending messages, there may be exceptions, network jitter, faults, etc. because the messages cannot be consumed, such as the user placing an order, consuming MQ acceptance, and the order system failure, resulting in the user's payment failure. At this time, the message middleware must support the message retry mechanism strategy. That is, support: in case of problems and failures, messages can be retransmitted without loss
Mechanism and comparison of message distribution strategies
What is the high availability mechanism
The so-called high availability refers to the ability of the product to perform the specified function under the specified conditions and at the specified time or time
When the business volume increases, the request is too large. A message middleware server will touch the limit of hardware (CPU, memory and disk). A message server can no longer meet the needs of the business, so the message middleware must support cluster deployment to achieve the purpose of high availability
Cluster mode 1 - deployment of master slave shared data
Cluster mode 2 - Master Slave synchronous deployment mode
Explanation: messages written in this mode are also on the Master node, but the Master node will synchronize data to the slave node to form a replica, which is very similar to the zookeeper or redis Master-slave mechanism. In this way, the effect of load balancing can be achieved. If consumers have multiple nodes, they can go to different nodes for consumption, thinking that the copy and synchronization of messages will occupy a lot of bandwidth and network resources. It will be used in the later rabbitmq
Cluster mode 3 - Multi master cluster synchronous deployment mode
Explanation: it is not very different from the above, but it can be written to any node
Cluster mode 4 - Multi master cluster forwarding deployment mode
Explanation: if the data you insert is broker-1 China, the metadata information will store the relevant description of the data and the location (queue) where the records are stored. It synchronizes the description information, that is, the metadata information. If consumers consume in broker-2 and find that their nodes do not have corresponding information, they can query from the corresponding metadata information, and then return the corresponding message information. Scenarios: for example, buy train tickets or scalpers buy concert tickets. For example, the first scalpers have concert tickets that customers say they want to buy, But he didn't, but he went back to contact other scalpers to ask, and if so, he returned
Cluster mode 5: a combination of master slave and broker cluster
Explanation: the multi master and multi slave hot standby mechanism is implemented to complete the high availability of messages and the hot standby mechanism of data. When the production scale reaches a certain stage, this kind of use frequency is relatively high
What is a highly reliable mechanism
The so-called high reliability means that the system can operate continuously without failure. For example, a sudden system crash, error reporting, abnormality, etc. do not affect the normal operation of online business. The probability of error is very low, which is called high reliability
In high concurrency business scenarios, if the high reliability of the system cannot be guaranteed, the hidden dangers and losses will be very serious
How to ensure the reliability of middleware messages can be considered from two aspects:
- Message transmission: ensure the correctness of data analysis between systems through protocols
- Reliable message storage: ensure the reliability of messages through persistence
2, Introduction and installation
1. RabbitMQ introduction and installation
https://www.bilibili.com/video/BV1dX4y1V73G?p=27
01 overview
Brief overview:
RabbitMQ is an open source, implemented in accordance with AMQP protocol and written in Erlang language. It supports a variety of clients (Languages) for storing and forwarding messages in distributed systems. It has the characteristics of high availability, high scalability and ease of use
02 download RabbitMQ
- Download address: https://www.rabbitmq.com/download.html
- Environment preparation: CentOS7.x + /Erlang
RabbitMQ is developed in Erlang language, so the system environment must provide Erlang environment. The first step is to install Erlang
View system version number
Install Download
mkdir -p /usr/rabbitmq ca /usr//rabbitmq # Upload the installation package to the linux system erlang-22.0.7-1.el7.x86_64.rpm rabbitmq-server-3.7.18-1.el7.noarch.rpm rpm -Uvh erlang-solutions-2.0-1.noarch.rpm yum install -y erlang erl -v
04 installing socat
Install Download
yum install -y socat
05 installing rabbitmq
Install Download
rpm -Uvh rabbitmq-server-3.7.18-1.el7.noarch.rpm yum install rabbitmq-server -y
Start service
# Start service systemctl start rabbitmq-server # View the service status, as shown in the figure systemctl status rabbitmq-server.service # Startup self startup systemctl enable rabbitmq-server # Out of Service systemctl stop rabbitmq-server
2. RabbitMQWeb management interface and authorization operation
01 RabbitMQ management interface
By default, the web client plug-in is not installed. It needs to be installed before it can take effect
rabbitmq-plugins enable rabbitmq_management
Note: rabbitmq has a default account and password: guest can only be accessed under localhost by default, so you need to add a remote login user
After installation, restart the service
systemctl restart rabbitmq-server
Remember to open port 15672 in the security group of the corresponding server (Alibaba cloud, Tencent cloud, etc.)
Access in browser
# 10. Turn off the firewall service systemctl disable firewalld Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service. systemctl stop firewalld # 11. Access the web management interface http://10.15.0.8:15672/
02 authorized account and password
New user
rabbitmqctl add_user admin admin
Set user assigned operation permissions
rabbitmqctl set_user_tags admin administrator
User level:
- administrator: you can log in to the console, view all information, and manage rabbitmq
- monitoring: the monitor logs in to the console to view all information
- policymaker: the policy maker logs in to the console and specifies the policy
- Management common administrator login console
Add resource permissions for users
rabbitmqctl set_permissions -p / admin ".*"".*"".*"
Web login succeeded
03 summary:
3. Docker installation of rabbitmq
01 Dokcer installing RabbitMQ
Get rabbit image
docker pull rabbitmq:management
Create and run containers
docker run -id --name=myrabbit -p 15672:15672 rabbitmq:management --hostname: Specifies the container host name --name:Specify container name -p: take mq Port number mapped to local Or set the user and password at runtime
start-up
Visit the web page successfully!
4. Role classification of rabbitmq
3, Introductory case
- Simple mode
- Work mode
- Publish subscribe mode
- Routing mode
- Topic mode
- Parameter mode
1. RabbitMQ introduction case - Simple mode
https://www.bilibili.com/video/BV1dX4y1V73G?p=44 Implementation steps
- jdk1.8
- Build a maven project
- Import maven dependency of rabbitmq
- Start rabbitmq server service
- Define producer
- Define consumer
- Observe the process of the message in the rabbitmq server service
01 build a maven project
02 import dependency
java Native dependency
<dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.10.0</version> </dependency>
03 first model
In the model above, there are the following concepts:
- The producer is the program that sends the message
- Consumer: the receiver of the message will always wait for the message to arrive.
- Message queue: the red part in the figure. Similar to a mailbox, messages can be cached; The producer delivers the message to it, and the consumer takes the message out of it.
producer
//Simple mode public class Producer{ //1. Create a connection factory ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("10.15.0.9"); connectionFactory.setPort(5672); connectionFactory.setUsername("admin"); connectionFactory.setPassword("admin"); connectionFactory.setVirtualHost("/"); Connection connection = connectionFactory.newConnection("producer"); //2. Create channel Channel channel = connection.createChannel(); //3. Create switches, declare queues, bind relationships, route key s, send and receive messages /*Parameter 1: whether to persist. Will non persistent messages be saved? The disk will be saved, but it will be lost when the server is restarted Parameter 2: exclusive queue Parameter 3: whether to delete automatically. Whether to delete the queue automatically after the last consumer message is completed Parameter 4: carry subsidiary attributes */ String queueName = "queue1"; channel.queueDeclare(queueName,false,false,false,null); //4. Send message to queue /*Parameter 1: switch Parameter 2: queue, routing key Parameter 3: status control of message Parameter 4: message subject */ //Interview question: can there be queues without switches? Impossible. Although no switch is specified, there must be a default switch String message = "Hello"; channel.basicPublish("",message, null,message.getBytes()); //5. Close channel.close(); connection.close(); }
consumer
//Simple mode public class Consumer{ //1. Create a connection factory ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("10.15.0.9"); connectionFactory.setPort(5672); connectionFactory.setUsername("admin"); connectionFactory.setPassword("admin"); connectionFactory.setVirtualHost("/"); Connection connection = connectionFactory.newConnection("producer"); //2. Create channel Channel channel = connection.createChannel(); //3. Accepted content channel.basicConsume("queue1",true,new DefaultConsumer(){ public void handle(String consumerTag, Delivery message) throws IOException { System.out.println(new String("The message is" + new String(meassage.getBody()),"UTF-8")); },new CancelCallback(){ public void handle(String consumerTag) throws IOException { System.out.println("Acceptance failed"); } }); //4. Close channel.close(); connection.close(); }
4. RabbitMQ entry case - fanout mode
01 publish subscribe mode of rabbitmq
graphic
- web operation viewing video
- Type: fanout
- Features: Fanout - publish and subscribe mode is a broadcast mechanism. It is a mode without routing key
producer
//Simple mode public class Producer{ //1. Create a connection factory ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("10.15.0.9"); connectionFactory.setPort(5672); connectionFactory.setUsername("admin"); connectionFactory.setPassword("admin"); connectionFactory.setVirtualHost("/"); Connection connection = connectionFactory.newConnection("producer"); //2. Create channel Channel channel = connection.createChannel(); //3. Create switches, declare queues, bind relationships, route key s, send and receive messages /*Parameter 1: whether to persist. Will non persistent messages be saved? The disk will be saved, but it will be lost when the server is restarted Parameter 2: exclusive queue Parameter 3: whether to delete automatically. Whether to delete the queue automatically after the last consumer message is completed Parameter 4: carry subsidiary attributes */ String queueName = "queue1"; channel.queueDeclare(queueName,false,false,false,null); //4. Send message to queue /*Parameter 1: switch Parameter 2: queue, routing key Parameter 3: status control of message Parameter 4: message subject */ //Interview question: can there be queues without switches? Impossible. Although no switch is specified, there must be a default switch String message = "Hello"; //5. Prepare the switch String exchangeName = "fanout-exchange"; //6. Define routing key String routeKey = ""; //7. Specify the type of switch String type = "fanout"; channel.basicPublish(exchangeName,routeKey, null,message.getBytes()); //8. Close channel.close(); connection.close(); }
consumer
The code is the same, just start the test with thread!
Switches and queues are not bound through code here, but through the visual interface!
5. RabbitMQ entry case - Direct mode
//6. Define routing key String routeKey = "email"; //7. Specify the type of switch String type = "direct"; channel.basicPublish(exchangeName,routeKey, null,message.getBytes());
6. RabbitMQ introduction case - Topic mode
//6. Define routing key String routeKey = "com.order.test.xxx"; //7. Specify the type of switch String type = "direct"; channel.basicPublish(exchangeName,routeKey, null,message.getBytes());
Code creation and binding
//5. Prepare the switch String exchangeName = "direct_message_exchange"; String exchangeType = "direct"; //If you use the interface to bind the relationship between queue and exchange first, the code does not need to write these declaration codes, which can make the code more concise //If we declare it in code, we need to learn //6. Declare that the so-called persistence of the switch refers to whether the switch will be lost with the server restart channel.exchangeDeclare(exchangeName,exchangeType,true); //7. Claim queue channel.queueDeclare("queue5",true,false,false,null); channel.queueDeclare("queue6",true,false,false,null); channel.queueDeclare("queue7",true,false,false,null); //8. Relationship between binding queue and switch channel.queueBind("queue5",exchangeName,"order"); channel.queueBind("queue6",exchangeName,"order"); channel.queueBind("queue7",exchangeName,"course"); channel.basicPublish(exchangeName,course, null,message.getBytes());
7. RabbitMQ entry case - Work mode
01 Work mode polling mode (round robin)
When there are multiple consumers, which consumer will consume our news, and how can we balance the amount of consumer consumption information?
There are two main modes:
- Distribution in polling mode: one for each consumer, distributed equally
- Fair distribution: fair distribution is carried out according to the consumption capacity of consumers, with more fast processing and less slow processing; distribution according to work
producer
Just like simple mode!
consumer
Create two of the same!
02 Work mode fair distribution mode
producer
Just like simple mode!
consumer
//Simple mode public class Consumer{ //3. Accepted content //Indicators are defined channel.basicQos(1); channel.basicConsume("queue1",false,new DefaultConsumer(){ public void handle(String consumerTag, Delivery message) throws IOException { System.out.println(new String("The message is" + new String(meassage.getBody()),"UTF-8")); //Change to manual response channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false); },new CancelCallback(){ public void handle(String consumerTag) throws IOException { System.out.println("Acceptance failed"); } }); //4. Close channel.close(); connection.close(); }
Create two of the same!
8. RabbitMQ usage scenario
01 decoupling, peak shaving, asynchronous
Synchronous asynchronous problem (serial)
Serial mode: after successfully writing the order information into the database, send the registration email and then send the registration SMS. After the above three tasks are completed, return to the client
public void makeOrder(){ //1. Send order //2. Send SMS service //3. Send email service //4. Send app service }
Parallel asynchronous thread pool
Parallel mode: after the order information is successfully written into the database, send the registration email and send the registration SMS at the same time. After the above three tasks are completed, return to the client. The difference from serial is that the parallel method can improve the processing time
public void test(){ //asynchronous theadpool.submit(new Callable<Object>{ //1. Send SMS service }) //asynchronous theadpool.submit(new Callable<Object>{ //2. }) //asynchronous theadpool.submit(new Callable<Object>{ //3. }) //asynchronous theadpool.submit(new Callable<Object>{ //4. }) }
Existing problems
- High coupling
- You need to write your own thread pool. The maintenance cost is too high
- Messages may be lost. You need to make message compensation yourself
- How to ensure the reliability of the message? Write it yourself
- If the server cannot be hosted, you need to write high availability
Asynchronous message queuing
Benefits:
- Fully decoupled, bridging with MQ
- There is an independent thread pool and running model
- If a message occurs, it may be lost. MQ has persistence function
- How to ensure the reliability of messages, dead letter queue and message transfer, etc
- If the server cannot be hosted, you need to write high availability, and the HA image model is high availability
According to the above agreement, the user's response time is equivalent to the time when the order information is written to the database, that is, 50 milliseconds. Register e-mail, send SMS, write to the message queue and return directly. Therefore, the speed of writing to the message queue is very fast and can be basically ignored. Therefore, the user's response time may be 50 milliseconds. Therefore, after the architecture is changed, the throughput of the system is increased to 20QPS per second. It is three times higher than serial and two times higher than parallel
02 high cohesion, low coupling
Benefits:
- Fully decoupled, bridging with MQ
- There is an independent thread pool and running model
- If a message occurs, it may be lost. MQ has persistence function
- How to ensure the reliability of messages, dead letter queue and message transfer, etc
- If the server cannot be hosted, you need to write high availability, and the HA image model is high availability
According to the above agreement, the user's response time is equivalent to the time when the order information is written to the database, that is, 50 milliseconds. Register e-mail, send SMS, write to the message queue and return directly. Therefore, the speed of writing to the message queue is very fast and can be basically ignored. Therefore, the user's response time may be 50 milliseconds. Therefore, after the architecture is changed, the throughput of the system is increased to 20QPS per second. It is three times higher than serial and two times higher than parallel
4, Springboot case
1. Fanout mode
https://www.bilibili.com/video/BV1dX4y1V73G?p=44
producer
application.yml
# Service port server: port: 8080 # Configure rabbitmq service spring: rabbitmq: username: admin password: admin virtual-host: / host: 127.0.0.1 port: 5672
OrderService.java
public class OrderService{ @Autowired private RabbitTemplate rabbitTemplate; //Simulated user orders public void makeOrder(String userid,String productid,int num){ //1. Query whether the inventory is sufficient according to the commodity id //2. Save order String orderId = UUID.randomUUID().toString(); sout("Order production succeeded:"+orderId); //3. Complete message distribution through MQ //Parameter 1: switch parameter 2: routing key/queue queue name parameter 3: message content String exchangeName = "fanout_order_exchange"; String routingKey = ""; rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId); } }
consumer
application.yml
# Service port server: port: 8080 # Configure rabbitmq service spring: rabbitmq: username: admin password: admin virtual-host: / host: 127.0.0.1 port: 5672
RabbitMqConfiguration.java
@Configuration public class RabbitMqConfiguration{ //1. Declare and register the switch in fanout mode @Bean public FanoutExchange fanoutExchange(){ return new FanoutExchange("fanout_order_exchange",true,false); } //2. Claim queue @Bean public Queue smsQueue(){ return new Queue("sms.fanout.queue",true); } @Bean public Queue duanxinQueue(){ return new Queue("duanxin.fanout.queue",true); } @Bean public Queue emailQueue(){ return new Queue("email.fanout.queue",true); } //3. Complete the binding relationship @Bean public Binding smsBingding(){ return BindingBuilder.bin(smsQueue()).to(fanoutExchange()); } @Bean public Binding duanxinBingding(){ return BindingBuilder.bin(duanxinQueue()).to(fanoutExchange()); } @Bean public Binding emailBingding(){ return BindingBuilder.bin(emailQueue()).to(fanoutExchange()); } }
FanoutSmsConsumer.java
@Component @RabbitListener(queue = {"sms.direct.queue"}) public class FanoutSmsConsumer{ @RabbitHandler public void reviceMessage(String message){ sout("sms The order information received is:"+message); } }
FanoutDuanxinConsumer.java
@Component @RabbitListener(queue = {"duanxin.direct.queue"}) public class FanoutDuanxinConsumer{ @RabbitHandler public void reviceMessage(String message){ sout("duanxin The order information received is:"+message); } }
FanoutEmailConsumer.java
@Component @RabbitListener(queue = {"duanxin.direct.queue"}) public class FanoutEmailConsumer{ @RabbitHandler public void reviceMessage(String message){ sout("email The order information received is:"+message); } }
2. Direct mode
producer
OrderService.java
public class OrderService{ @Autowired private RabbitTemplate rabbitTemplate; //Simulated user orders public void makeOrder(String userid,String productid,int num){ //1. Query whether the inventory is sufficient according to the commodity id //2. Save order String orderId = UUID.randomUUID().toString(); sout("Order production succeeded:"+orderId); //3. Complete message distribution through MQ //Parameter 1: switch parameter 2: routing key/queue queue name parameter 3: message content String exchangeName = "direct_order_exchange"; String routingKey = ""; rabbitTemplate.convertAndSend(exchangeName,"email",orderId); rabbitTemplate.convertAndSend(exchangeName,"duanxin",orderId); } }
consumer
RabbitMqConfiguration.java
@Configuration public class RabbitMqConfiguration{ //1. Declare and register the switch in fanout mode @Bean public DirectExchange directExchange(){ return new DirectExchange("direct_order_exchange",true,false); } //2. Claim queue @Bean public Queue smsQueue(){ return new Queue("sms.direct.queue",true); } @Bean public Queue duanxinQueue(){ return new Queue("duanxin.direct.queue",true); } @Bean public Queue emailQueue(){ return new Queue("email.direct.queue",true); } //3. Complete the binding relationship @Bean public Binding smsBingding(){ return BindingBuilder.bin(smsQueue()).to(fanoutExchange()).with("sms"); } @Bean public Binding duanxinBingding(){ return BindingBuilder.bin(duanxinQueue()).to(fanoutExchange()).with("duanxin"); } @Bean public Binding emailBingding(){ return BindingBuilder.bin(emailQueue()).to(fanoutExchange()).with("email"); } }
3. Topic mode
producer
public class OrderService{ @Autowired private RabbitTemplate rabbitTemplate; //Simulated user orders public void makeOrder(String userid,String productid,int num){ //1. Query whether the inventory is sufficient according to the commodity id //2. Save order String orderId = UUID.randomUUID().toString(); sout("Order production succeeded:"+orderId); //3. Complete message distribution through MQ //Parameter 1: switch parameter 2: routing key/queue queue name parameter 3: message content String exchangeName = "direct_order_exchange"; String routingKey = "com.duanxin"; rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId); } }
Consumer (using notes)
FanoutSmsConsumer.java
@Component @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "sms.topic.queue",durable = "true",antoDelete = "false"), exchange = @Exchange(value = "topic_order_exchange",type = "ExchangeTypes.TOPIC") key = "#.sms.#" )) public class TopicSmsConsumer{ @RabbitHandler public void reviceMessage(String message){ sout("sms The order information received is:"+message); } }
FanoutDuanxinConsumer.java
@Component @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "duanxin.topic.queue",durable = "true",antoDelete = "false"), exchange = @Exchange(value = "topic_order_exchange",type = "ExchangeTypes.TOPIC") key = "#.duanxin.#" )) public classTopicDuanxinConsumer{ @RabbitHandler public void reviceMessage(String message){ sout("duanxin The order information received is:"+message); } }
FanoutEmailConsumer.java
@Component @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "email.topic.queue",durable = "true",antoDelete = "false"), exchange = @Exchange(value = "topic_order_exchange",type = "ExchangeTypes.TOPIC") key = "#.email.#" )) public class TopicEmailConsumer{ @RabbitHandler public void reviceMessage(String message){ sout("email The order information received is:"+message); } }
5, RabbitMQ advanced
##1. Expiration time TTL
https://www.bilibili.com/video/BV1dX4y1V73G?p=44
summary
The expiration time TTL indicates that the expected time can be set for the message and can be received by the consumer within this time; After that, the message will be deleted automatically. RabbitMQ can set TTL for messages and queues. At present, there are two methods to set TTL
- The first method is to set the queue property so that all messages in the queue have the same expiration time
- The second method is to set the message separately, and the TTL of each message can be different
If the above two methods are used at the same time, the expiration time of the message shall be subject to the value with the smaller TTL. Once the lifetime of the message in the queue exceeds the set TTL value, it is called dead message. It is delivered to the dead letter queue, and the consumer will no longer receive the message
Set queue TTL
RabbitMqConfiguration.java
@Configuration public class TTLRabbitMQConfiguration{ //1. Declare and register the switch in direct mode @Bean public DirectExchange ttldirectExchange(){ return new DirectExchange("ttl_direct_exchange",true,false);} //2. Expiration time of the queue @Bean public Queue directttlQueue(){ //Set expiration time Map<String,Object> args = new HashMap<>(); args.put("x-message-ttl",5000);//This must be of type int return new Queue("ttl.direct.queue",true,false,false,args);} @Bean public Binding ttlBingding(){ return BindingBuilder.bin(directttlQueue()).to(ttldirectExchange()).with("ttl"); } }
Set message TTL
public class OrderService{ @Autowired private RabbitTemplate rabbitTemplate; //Simulated user orders public void makeOrder(String userid,String productid,int num){ //1. Query whether the inventory is sufficient according to the commodity id //2. Save order String orderId = UUID.randomUUID().toString(); sout("Order production succeeded:"+orderId); //3. Complete message distribution through MQ //Parameter 1: switch parameter 2: routing key/queue queue name parameter 3: message content String exchangeName = "ttl_order_exchange"; String routingKey = "ttlmessage"; //Set expiration time for messages MessagePostProcessor messagePostProcessor = new MessagePostProcessor(){ public Message postProcessMessage(Message message){ //Here is the string message.getMessageProperties().setExpiration("5000"); message.getMessageProperties().setContentEncoding("UTF-8"); return message; } } rabbitTemplate.convertAndSend(exchangeName,routingKey,orderId,messagePostProcessor); } }
RabbitMqConfiguration.java
@Configuration public class TTLRabbitMQConfiguration{ //1. Declare and register the switch in direct mode @Bean public DirectExchange ttldirectExchange(){ return new DirectExchange("ttl_direct_exchange",true,false);} //2. Expiration time of the queue @Bean public Queue directttlQueue(){ //Set expiration time Map<String,Object> args = new HashMap<>(); args.put("x-message-ttl",5000);//This must be of type int return new Queue("ttl.direct.queue",true,false,false,args);} @Bean public Queue directttlMessageQueue(){ return new Queue("ttlMessage.direct.queue",true,false,false,args);} @Bean public Binding ttlBingding(){ return BindingBuilder.bin(directttlMessageQueue()).to(ttldirectExchange()).with("ttlmessage"); } }
2. Dead letter queue
summary
DLX, fully known as dead letter exchange, can be called dead letter switch or dead letter mailbox. When a message becomes dead letter in another queue, it can be re sent to another switch, which is DLX. The queue bound to DLX is called dead letter queue. The message may become dead letter due to the following reasons:
- Message rejected
- Message expiration
- The queue has reached its maximum length
DLX is also a normal switch. It is no different from a general switch. It can be specified on any queue. In fact, it is to set the properties of a queue. When there is dead letter in this queue, Rabbitmq will automatically republish the message to the set DLX, and then route it to another queue, that is, dead letter queue.
To use dead letter queue, you only need to set the queue parameter x-dead-letter-exchange to specify the switch when defining the queue
code
DeadRabbitMqConfiguration.java
@Configuration public class DeadRabbitMqConfiguration{ //1. Declare and register the switch in direct mode @Bean public DirectExchange deadDirect(){ return new DirectExchange("dead_direct_exchange",true,false);} //2. Expiration time of the queue @Bean public Queue deadQueue(){ return new Queue("dead.direct.queue",true);} @Bean public Binding deadbinds(){ return BindingBuilder.bind(deadDirect()).to(deadQueue()).with("dead"); } }
RabbitMqConfiguration.java
@Configuration public class TTLRabbitMQConfiguration{ //1. Declare and register the switch in direct mode @Bean public DirectExchange ttldirectExchange(){ return new DirectExchange("ttl_direct_exchange",true,false);} //2. Expiration time of the queue @Bean public Queue directttlQueue(){ //Set expiration time Map<String,Object> args = new HashMap<>(); //args.put("x-max-length",5); args.put("x-message-ttl",5000);//This must be of type int args.put("x-dead-letter-exchange","dead_direct_exchange"); args.put("x-dead-letter-routing-key","dead");//fanout does not need to be configured return new Queue("ttl.direct.queue",true,false,false,args);} @Bean public Queue directttlMessageQueue(){ return new Queue("ttlMessage.direct.queue",true,false,false,args);} @Bean public Binding ttlBingding(){ return BindingBuilder.bin(directttlMessageQueue()).to(ttldirectExchange()).with("ttlmessage"); } }