Why Reactive Spring?
为什么 使用响应式 的spring
In this chapter, we are going to explain the concept of reactivity,looking at why reactive approaches are better than traditional approaches. To do this, we will look at examples in which traditional approaches failed. In addition to this, we will explore the fundamental principles of building a robust system(健壮的系统), which is mostly referred to as reactive systems. We will also take an overview of (讲一下)the conceptual reasons for building message-driven(消息驱动机制) communication between
…
总结:响应式编程比传统的编程要好很多
2.(Message-Driven) 信息驱动
(Event-Driven)事件驱动
(Streaming)
他们的详解 请移步至 :各种驱动总结
distributed servers, covering business cases in which reactivity fits well.Then, we will expand the meaning of reactive programming to build a fine-grained (粒度更加精细)reactive system. We will also discuss why the Spring Framework team decided to include a reactive approach as the core part of Spring Framework 5(为啥spring框架决定把响应式方法作为spring5的核心). Based on the content of this chapter, we will understand the importance of reactivity and why it is a good idea to move our projects to the reactive world.
…
1.分布式系统比较适合 响应式编程
各种夸夸…
Why reactive?
Nowadays,reactiveis a buzzword—so exciting but so confusing.However, should we still care about reactivity even if it takes an honorable place in conferences around the world? If we google the word reactive, we will see that the most popular association is programming, in which it defines the meaning of a programming model. However, that is not the only meaning for reactivity. Behind that word, there are hidden fundamental design principles aimed at building a robust system. To understand the value of reactivity as an essential design principle, let’s imagine that we are developing a small business.
1.响应式很流行,但是也很让人难以理解 (如果你熟悉异步非阻塞 (不存在异步阻塞,异步天然非阻塞) 这一块也是很好理解的…)
2.你去网上搜索 基本都是语法而已 ,但是 语法并不代表着 spring响应式编程!!!!!!!!!!!!!
3. spring响应式编程 是为了构建一个更加健壮的系统咯
Suppose our small business is a web store with a few cutting-edge (领先的 )products at an attractive price. As is the case with the majority of projects in this sector, we will hire software engineers to solve any problems that we encounter. We opted for(选择) the traditional approaches to development, and, during a few development interactions, we created our store.
1.我们要开发一个网上商店
Usually, our service is visited by about one thousand users per hour. To serve the usual demand, we bought a modern computer and ran the Tomcat web server as well as configuring Tomcat’s thread pool with 500 allocated threads. The average response time for the majority of user requests is about 250 milliseconds. By doing a naive calculation of the capacity for that configuration, we can be sure that the system can handle about 2,000 user requests per second. According to statistics,the number of users previously mentioned produced around 1,000 requests per second on average. Consequently,the current system’s capacity will be enough for the average load.
1.项目再tomcat启动 ,有500线程
2.用户响应时间2.5s
3.系统能处理2000qps
总结就是自己的系统能处理高并发
Black Friday is a valuable day for both customers and retailers. For the customer, it is a chance to buy goods at discounted prices. And for retailers(零售商), it is a way to earn money and popularize products. However, this day is characterized by an unusual influx of clients(大量的用户), and that may be a significant cause of failure in production.
没什么重点…
And, of course, we failed! At some point in time, the load exceeded all expectations. There were no vacant threads in the thread pool to process user requests. In turn, the backup server was not able to handle such an unpredictable invasion(入侵), and, in the end, this caused a rise inthe(真正的) response time(响应超时) and periodic(定时的) service outage(中断). At this point, we started losing someuser requests, and, finally, our clients became dissatisfied and preferred dealing with competitors.
1.项目失败了,因为没有多余的线程 来处理用户
2.用户滚去竞争对手那里了…
In the end, a lot of potential (潜在的)customers and money were lost, and the store’s rating (等级)decreased. This was all a result of the fact thatwe couldn’t stay responsive under the increased workload.
But, don’t worry, this is nothing new. At one point in time, giants such as Amazon and Walmart also faced this problem and have since found a solution. Nevertheless, we will follow the same roads as our predecessors(前辈), gaining an understanding of the central principles of designing robust systems and then providing a general definition for them.To learn more about giants failures see:
1.转折 ,这没啥稀奇的, 亚马逊和沃尔玛一开始还不是这鬼样子…
我们追随者前辈们,获得了一个设计健壮系统的核心原则,并且有一个解决他们的通用的方法
Now, the central question that should remain in our minds is—How should we be responsive? As we might now understand from the example given previously, an application should react to changes. This should include changes in demand (load)and changes in the availability of external services. In other words, it should be reactive to any changes that may affect the system’s ability to respond to user requests.
1.产品需要改变,就现在~~
One of the first ways to achieve the primary goal is through elasticity. This describes the ability to stay responsive under a varying workload, meaning that the throughput (吞吐量)of the system should increase automatically when more users start using it and it should decrease automatically。when the demand goes down. From the application perspective, this feature enables system responsiveness because at any point in time the system can be expanded without affecting the average latency( 平均等待时间).
1.系统应该具有弹性,(此处与弹性云服务器不谋而合),用户量大的时候系统应该变流弊(系统吞吐量增加),小的时候系统应该稍微摆烂。这样才不会浪费cpu资源。
2.产品应该 在不同工作量的情况下保证持续的向客户端响应
Note that latency is the essential characteristic of responsiveness. Without elasticity, growing demand will cause the growth of average latency, which directly affects the responsiveness of the system.
1.一个具有弹性的系统 可以降低用户等待事件
we defined the request handler which will be invoked on users’requests. In turn, each invocation of the handler produces an additional HTTP call to an external service and then subsequently executes another processing stage. Despite the fact that the preceding code may look familiar and transparent in terms of logic, it has some flaws. To understand what is wrong in this example, let’s take an overview of the followingrequest’s timeline:
1.作者做了一个简单的restful 风格的http响应,a服务调用b服务
This diagram depicts the actual behavior of the corresponding code. As we may notice, only a small part of the processing time is allocated for effective CPU usage whereas the rest of the time thread is being blocked by the I/O and cannot be used for handling other requests.
总结: 由上图可以知道 ,在一个分布式系统中,a服务掉b服务,b服务在处理a服务的请求的时候,a服务回空闲等待,这样浪费了cpu性能。a服务的io会被阻塞
In some languages, such as C#, Go, and Kotlin, the same code might be non-blocking when green threads are used. However, in pure Java, we do not have such features yet. Consequently, the actual thread will be blocked in such cases.
java很垃圾,别的语言都不会被阻塞
On the other hand, in the Java world, we have thread pools, which may allocate additional threads to increase parallel processing(并行处理). However, under a high load, such a technique may be extremely inefficient to process the new I/O task simultaneously. We will revisit this problem again during this chapter and also analyze it thoroughly in Chapter 6, WebFlux Async Non-Blocking Communication.
We will revisit this problem again during this chapter and also analyze it thoroughly in Chapter 6, WebFlux Async Non-Blocking Communication.
1.我们可以使用线程池来解决这个问题,开辟一条新线程来解决问题(者很容器出现上下文丢失的情况 ,假如你把用户信息保存在threadLocal ,开辟一条新线程 就会出现上下文丢失,threadLocal 保存的信息直接全部丢失咯),但是这样在同时处理新的一条任务情况下并不好,这会在第六章详细讲解
Nonetheless, we can agree that to achieve better resource utilization in I/O cases, we should use an asynchronous and non-blocking interaction model. In real life, this kind of communication is messaging. When we get a message (SMS, or email), all our time is taken up by reading and responding. Moreover, we do not usually wait for the answer and work on other tasks in the meantime. Unmistakably(在这种情况下), in that case, work is optimized and the rest of the time may be utilized efficiently. Take a look at the following diagram:
1.我们可以使用异步非阻塞的模型来应对上面的问题 。
2.你不可能在发一个微信消息的时候一直等待(舔狗除外 …),你可以在等待他们回复消息的时候淦别的事情
In general, to achieve efficient resource utilization when communicating between services in a distributed system, we have to embrace the message-driven communication principle(信息驱动原则). The overall interaction between services may be described as follows—each element awaits the arrival of messages and reacts to them, otherwise lying dormant(休眠), and vice versa(反之亦然), a component should be able to send a message in the non-blocking fashion. Moreover, such an approach to communication improves system scalability by enabling location transparency. When we send an email to the recipient, we care about the correctness of the destination address. Then the mail server takes care of delivering that email to one of the available devices of the recipient. This frees us from concerns about the certain device,allowing recipients to use as many devices as they want. Furthermore, it improves failure tolerance (失败容错)since the failure of one of the devices does not prevent recipients from(避免) reading an email from another device.
这里讲的是信息驱动,人发邮件只需要关注 对方的通信地址是否正确,邮箱服务关注 将邮件发送给接收者,这让我们避免关注 邮箱服务关注的内容
One of the ways to achieve message-driven communication is by employing a message broker(代理). In that case, by monitoring the message queue, the system is able to control the load management (负载管理)and elasticity. Moreover, the message communication gives clear flow control and simplifies the overall design. We will not get into specific details of this in this chapter, as we will cover the most popular techniques for achieving message-driven communication in Chapter 8, Scaling Up with Cloud Streams.
By embracing all of the previous statements, we will get the foundational principles of the reactive system. This is depicted in the following diagram:
这里讲的就是类似于 rabbitmq 的机制,消息队列存放消息,一个消息监听者监听消息,具体详情在第八章 。
In the previous section, we learned the importance of reactivity and the fundamental principles of the reactive system, and we have seen why message-driven communication is an essential constituent of the reactive ecosystem. Nonetheless, to reinforce what we have learned, it is necessary to touch on real-world examples of its application. First of all, the reactive system is about architecture, and it may be applied anywhere. It may be used in simple websites, in large enterprise solutions, or even in fast-streaming or big-data systems.But let’s start with the simplest—consider the example of a web store that we have already seen in the previous section. In this section, we will cover possible improvement and changes in the design that may help in achieving a reactive system. The following diagram helps us get acquainted with the overall architecture of the proposed solution:
To understand whether imperative programming follows reactive system design principles,let’s consider the next diagram:
interface ShoppingCardService {
(1) Output calculate(Input value);
}
class OrdersService {
private final ShoppingCardService scService;
void process() {
Input input = ...;
Output output = scService.calculate(input);
...
}
}
The aforementioned code is explained as follows:This is the ShoppingCardService interface declaration. This corresponds to the aforementioned class diagram and has only one calculate method, which accepts one argument and returns a response after its processing.This is the OrderService declaration. Here, at point (2.1) we synchronously call ShoppingCardServiceand receive a result right after its execution. Point (2.2) hides the rest of the code responsible for result processing.
This is the OrderService declaration. Here, at point (2.1) we synchronously call ShoppingCardServiceand receive a result right after its execution. Point (2.2) hides the rest of the code responsible for result processing.In turn, in that case our services are tightly coupled in time, or simplythe execution of OrderService is tightly coupled to the execution ofShoppingCardService. Unfortunately, with such a technique, we cannot proceed with any other actions while ShoppingCardService is in the processing phase.
As we can understand from the preceding code, in Java world, the execution of scService.calculate(input) blocks the Thread on which the processing of theOrdersService logic takes place. Thus, to run a separate independent processing in OrderService we have to allocate an additional Thread.As we will see in this chapter, the allocation of an additional Thread might be wasteful. Consequently, from the reactive system perspective, such system behavior is unacceptable.