This is an automated email from the ASF dual-hosted git repository. hyunkun pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/dubbo-website.git
The following commit(s) were added to refs/heads/master by this push: new 848ed07 Translation of dubboAsync_server.md (#466) 848ed07 is described below commit 848ed075d643742dd9d14b32f3dca45b2e340b51 Author: Kyle <fightzyf1...@hotmail.com> AuthorDate: Sun Sep 29 13:25:42 2019 +0800 Translation of dubboAsync_server.md (#466) --- blog/en-us/dubboAsync_server.md | 98 +++++++++++++++++++++++++++++++++++++++++ blog/zh-cn/dubboAsync_server.md | 24 +++++----- site_config/blog.js | 7 +++ 3 files changed, 116 insertions(+), 13 deletions(-) diff --git a/blog/en-us/dubboAsync_server.md b/blog/en-us/dubboAsync_server.md new file mode 100644 index 0000000..8284cf2 --- /dev/null +++ b/blog/en-us/dubboAsync_server.md @@ -0,0 +1,98 @@ +--- +title: Implementation background and practice of Dubbo server asynchronous interface +keywords: Dubbo, Asynchrony, Reactive +description: Implementation background and practice of Dubbo server asynchronous interface +--- + +# Implementation background and practice of Dubbo server asynchronous interface + +## Preface +It is suggested to make an understanding of the thread phase involved in the process of Dubbo first, please refer to [Implementation background and practice of Dubbo client asynchronous interface](http://dubbo.apache.org/en-us/blog/dubboAsync_client.html) for details. + +## Implementation background +It is necessary to introduce the server-side thread strategy in more detail to deepen the user's judgment basis for selecting server-side asynchrony. It is also necessary to introduce coroutines, the "secret weapon" often used in server-side asynchrony. + +### Server-side thread strategy +Dubbo supports a variety of NIO frameworks to implement remoting protocols. Whether Netty, Mina or Grizzly, the implementations are much the same. They are all based on event-driven methods to establish network channels and read data streams. Taking introduction to [Thread Strategy](https://javaee.github.io/grizzly/iostrategies.html) of Grizzly as an example, the following four categories are usually supported. Dubbo as an RPC framework, the default choice is the first strategy. Because [...] +1. __Worker-thread Strategy__ + +The most useful IOStrategy, where Selector thread delegates NIO events processing to a worker threads. + + + +![workerthread-strategy.png | center | 371x244](../../img/blog/dubboasyn_server/1.png "") + + +This IOStrategy is very scalable and safe. We can change the size of selector and worker thread pool as required and there is no risk that some problem, which may occur during the specific NIO event processing, will impact other Channels registered on the same Selector. + +The disadvantage is the cost of thread context switching. + +2. __Same-thread Strategy__ + +Potentially the most efficient IOStrategy. Unlike the worker-thread IOStrategy, the same-thread IOStrategy processes NIO events in the current thread, avoiding expensive thread context switches. + + +![samethread-strategy.png | center | 389x264](../../img/blog/dubboasyn_server/2.png "") + + +This IOStrategy is still pretty scalable, because we can tune the selector thread pool size, but it does have drawbacks. Care needs to be taken that channel NIO event processing won’t block or execute any long lasting operation, because it may block the processing of other NIO events that occur on the same Selector. + +3. __Dynamic Strategy__ + +As mentioned previously worker-thread and same-thread strategies have distinct advantages and disadvantages. However, what if a strategy could try to swap them smartly during runtime depending on the current conditions (load, gathered statistics… etc)? + + +![dynamic-strategy.png | center | 361x387](../../img/blog/dubboasyn_server/3.png "") + + +Potentially this IOStrategy could bring a lot of benefit and allow finer control of the resources. However, it’s important to not overload the condition evaluation logic, as its complexity will make this IOStrategy inefficient comparing to previous two strategies. + +By the way, I want you to pay more attention to this strategy, which is probably the best combination of Dubbo server asynchrony. + +4. __Leader-follower Strategy__ + + +![leaderfollower-strategy.png | center | 443x286](../../img/blog/dubboasyn_server/4.png "") + +This IOStrategy is similar to worker-thread IOStrategy, but instead of passing NIO event processing to a worker thread, it changes worker thread to a selector thread by passing it the control over Selector and the actual NIO event processing takes place in the current thread. This strategy actually confuses worker and IO thread stages, which is not recommended. + +### Coroutine and thread +In terms of CPU resource management, the minimum scheduling unit of OS and JVM is thread. The coroutine library implemented by business application through extension can have independent running unit. In fact, it is also done based on thread. The principle should be to save the context and switch to another coroutine when IO blocking or lock waiting is encountered. + +__In the default Dubbo thread strategy, there are worker thread pools to execute the business logic, but the ThreadPool Full problem often occurs. In order to release worker threads as soon as possible, another thread will be set up in the implementation of the business service. The cost is thread context switching again, and it's necessary to consider link-level data transfer (such as tracing information) and flow-control export controls, etc. Of course, if Dubbo can switch to the Same- [...] + +## The sample + +Use an example to experience the Dubbo server-side asynchronous interface. For Demo code, visit [https://github.com/dubbo/dubbo-samples/tree/master/dubbo-samples-notify](https://github.com/dubbo/dubbo-samples/tree/master/dubbo-samples-notify)。 + +```java +public class AsyncServiceImpl implements AsyncService { + + @Override + public String sayHello(String name) { + System.out.println("Main sayHello() method start."); + final AsyncContext asyncContext = RpcContext.startAsync(); + new Thread(() -> { + asyncContext.signalContextSwitch(); + System.out.println("Attachment from consumer: " + RpcContext.getContext().getAttachment("consumer-key1")); + System.out.println(" -- Async start."); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + asyncContext.write("Hello " + name + ", response from provider."); + System.out.println(" -- Async end."); + }).start(); + System.out.println("Main sayHello() method end."); + return "hello, " + name; + } + +``` +## Practical suggestions +* Don't rely too much on server-side asynchrony. +* Server-side asynchrony is basically a false proposition in the face of event-driven or Reactive.<span data-type="color" style="color:rgb(36, 41, 46)"><span data-type="background" style="background-color:rgb(255, 255, 255)">Supplement the reason: the server asynchrony is said Dubbo server-side business threads (default is 200) is not enough, but in the Event-Driven mode, 200 threads certainly do not need that much, just as much as the number of CPU cores. As long as the business impleme [...] +* To use server-side asynchrony, it is recommended that the server-side thread strategy adopt the Same_thread pattern + Coroutine Library. + +## Conclusions +When Dubbo supports business applications, it encounters a variety of requirements scenarios, and server-side asynchrony provides users with a solution to deal with ThreadPool Full. In the case of ThreadPool Full, if the current system bottleneck is CPU, this solution is not recommended. If the system load is not high, increasing the number of worker threads or using server asynchrony can be considered. diff --git a/blog/zh-cn/dubboAsync_server.md b/blog/zh-cn/dubboAsync_server.md index f05d4b8..e1c3306 100644 --- a/blog/zh-cn/dubboAsync_server.md +++ b/blog/zh-cn/dubboAsync_server.md @@ -1,5 +1,5 @@ --- -title: Dubbo客户端异步接口的实现背景和实践 +title: Dubbo服务端异步接口的实现背景和实践 keywords: Dubbo, 异步, Reactive description: Dubbo服务端异步接口的实现背景和实践 --- @@ -13,9 +13,8 @@ description: Dubbo服务端异步接口的实现背景和实践 有必要比较详细点的介绍下服务端的线程策略来加深用户在选择服务端异步的判断依据,同时有必要引出协程这一在服务端异步中常常会用到的“秘密武器”。 ### 服务端的线程策略 -Dubbo是支持多种NIO框架来做Remoting的协议实现,无论是Netty,Mina或者Grizzly,实现都大同小异,都是基于事件驱动的方式来做网络通道建立,数据流读取的,其中Grizzly对于线程策略介绍的为例,通常支持以下四种。Dubbo作为一个RPC框架,默认选择的是第一种策略,原因在于业务服务是CPU密集型还是IO阻塞性,是无法断定的,第一种策略是最保险的策略。当然,对于这几种策略有了了解后,再结合业务场景做针对性的选择是最完美的。 -1. __Worker-thread - 策略__ +Dubbo支持多种NIO框架来做Remoting的协议实现,无论是Netty,Mina或者Grizzly,实现都大同小异,都是基于事件驱动的方式来做网络通道建立,数据流读取的。其中以Grizzly对于[线程策略](https://javaee.github.io/grizzly/iostrategies.html)的介绍为例,通常支持以下四种。Dubbo作为一个RPC框架,默认选择的是第一种策略,原因在于业务服务是CPU密集型还是IO阻塞型,是无法断定的,第一种策略是最保险的策略。当然,对于这几种策略有了了解后,再结合业务场景做针对性的选择是最完美的。 +1. __Worker-thread策略__ 最常用最普适的策略,其中IO线程将NIO事件处理委托给工作线程。 @@ -24,7 +23,8 @@ Dubbo是支持多种NIO框架来做Remoting的协议实现,无论是Netty,Mi ![workerthread-strategy.png | center | 371x244](../../img/blog/dubboasyn_server/1.png "") -此策略具有很高的伸缩性。我们可以根据需要更改IO和worker线程池的大小,并且不存在在特定NIO事件处理期间可能发生的某些问题将影响在同一IO线程上注册的其他通道的风险。 +此策略具有很高的伸缩性。我们可以根据需要更改IO和worker线程池的大小,并且不存在在特定NIO事件处理期间可能发生的,同一Selector各个Channel之间相互干扰的风险。 + 缺点是有线程上下文切换的代价。 2. __Same-thread策略__ @@ -35,9 +35,9 @@ Dubbo是支持多种NIO框架来做Remoting的协议实现,无论是Netty,Mi ![samethread-strategy.png | center | 389x264](../../img/blog/dubboasyn_server/2.png "") -考虑到这个策略可以调整IO线程池大小,是具备可伸缩性;缺点也很明显,它要求业务处理中一定不要有阻塞处理,因为它可能会阻止在同一个IO线程上发生的其他NIO事件的处理。 +这个策略可以调整IO线程池大小,也是具备可伸缩性;缺点也很明显,它要求业务处理中一定不要有阻塞处理,因为它可能会阻止在同一个IO线程上发生的其他NIO事件的处理。 -3. dynamic__策略__ +3. __Dynamic策略__ 如前所述,前两种策略具有明显的优点和缺点。但是,如果策略可以尝试在运行时根据当前条件(负载,收集的统计信息等)巧妙地交换它们,何如? @@ -48,8 +48,7 @@ Dubbo是支持多种NIO框架来做Remoting的协议实现,无论是Netty,Mi 这种策略可能会带来很多好处,能更好地控制资源,前提是不要使条件评估逻辑过载,防止评估判断的复杂性会使这种策略效率低下。 多说一句,希望大家对这个策略多留意一下,它可能是Dubbo服务端异步方式的最佳搭配。我也多扯个淡,这几天关注了些adaptive XX或者predictive XX,这里看到dynamic真是亲切,Dubbo作为产品级生产级的微服务解决方案,是必须既要adaptive,又要predictive,还要dynamic,哈哈。 -4. __Leader-follower __ - 策略 +4. __Leader-follower策略__ @@ -88,10 +87,9 @@ public class AsyncServiceImpl implements AsyncService { ``` ## 实践建议 -* 不用迷信服务端异步 -* 不要迷信服务端异步 -* 服务端异步在Event-Driven或者Reactive面前基本是伪命题.<span data-type="color" style="color:rgb(36, 41, 46)"><span data-type="background" style="background-color:rgb(255, 255, 255)">补充下原因:服务端异步初衷是说Dubbo的服务端业务线程数(默认是200个)不够,但其实在event-driven模式下, 200个肯定不需要那么多,只需要cpu核数那样就可以,只要业务实现是非阻塞的纯异步方式的非阻塞的业务逻辑处理,用再多的线程数就是浪费资源。</span></span> -* 要用服务端异步,建议服务端的线程策略采用same thread模式+协程包 +* 不要迷信服务端异步。 +* 服务端异步在Event-Driven或者Reactive面前基本是伪命题.<span data-type="color" style="color:rgb(36, 41, 46)"><span data-type="background" style="background-color:rgb(255, 255, 255)">补充下原因:服务端异步初衷是说Dubbo的服务端业务线程数(默认是200个)不够,但其实在event-driven模式下,200个肯定不需要那么多,只需要cpu核数那样就可以。只要业务实现是非阻塞的纯异步方式的业务逻辑处理,用再多的线程数都是浪费资源。</span></span> +* 要用服务端异步,建议服务端的线程策略采用same thread模式+协程包。 ## 小结 Dubbo在支持业务应用时,会碰到千奇百怪的需求场景,服务端异步为用户提供了一种解决ThreadPool Full的方案。当发生ThreadPool Full的情况下,如果当前系统瓶颈是CPU,不建议用这种方案;如果系统Load不高,调高worker的线程数目,或者采用服务端异步,都是可以考虑的。 \ No newline at end of file diff --git a/site_config/blog.js b/site_config/blog.js index 7003781..11cab5e 100644 --- a/site_config/blog.js +++ b/site_config/blog.js @@ -11,6 +11,13 @@ export default { link: '/en-us/blog/service-test.html', }, { + title: 'Implementation background and practice of Dubbo server asynchronous interface', + author: '@JeffLv', + dateStr: 'Feb 20th, 2019', + desc: 'Implementation background and practice of Dubbo server asynchronous interface', + link: '/en-us/blog/dubboAsync_server.html', + }, + { title: 'Implementation background and practice of Dubbo client asynchronous interface', author: '@JeffLv', dateStr: 'Feb 20th, 2019',