`
sillycat
  • 浏览: 2542566 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

WebFlux and Reactive(1)Performance Basic Compare

 
阅读更多
WebFlux and Reactive(1)Performance Basic Compare

Unit test and Compare
https://blog.51cto.com/liukang/2090202

Create non-blocking
https://stackoverflow.com/questions/42299455/spring-webflux-and-reading-from-database
Wrap a blocking call
https://projectreactor.io/docs/core/release/reference/#faq.wrap-blocking

Follow this blog and do some of my testing
https://blog.51cto.com/liukang/2090202

The sample codes are all here
https://github.com/luohuazju/sillycat-spring-cloud

Wrk Performance Testing
Check the open files limit on MAC
> ulimit -n
256

> ulimit -n 2048

After set it bigger, check again
> ulimit -n
2048

Some test results from my samples
For tomcat in traditional MVC 200 threads and request per thread Model
> wrk -t30 -c3000 -d60s http://localhost:8081/hello/100
Running 1m test @ http://localhost:8081/hello/100
  30 threads and 3000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   857.16ms  310.59ms   1.14s    81.18%
    Req/Sec    64.16     28.50   210.00     71.56%
  105101 requests in 1.00m, 15.64MB read
Requests/sec:   1749.14
Transfer/sec:    266.47KB

For jetty in flux/mono in servlet3.1 adapter mod in jetty
> wrk -t30 -c3000 -d60s http://localhost:8082/hello/100
Running 1m test @ http://localhost:8082/hello/100
  30 threads and 3000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   450.88ms  221.82ms   1.98s    75.98%
    Req/Sec   126.44     62.90   460.00     67.91%
  199631 requests in 1.00m, 27.61MB read
Requests/sec:   3321.27
Transfer/sec:    470.30KB

For netty in flux/mono
> wrk -t30 -c3000 -d60s http://localhost:8083/hello/100
Running 1m test @ http://localhost:8083/hello/100
  30 threads and 3000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   104.63ms    6.99ms 585.20ms   91.82%
    Req/Sec   532.40    195.94     0.91k    69.98%
  872104 requests in 1.00m, 89.82MB read
Requests/sec:  14514.76
Transfer/sec:      1.49MB

Add - - timeout and - - latency in the parameters

> wrk -t16 -c100 -d60s --timeout 10s http://127.0.0.1:8083/hello/100 --latency
Running 1m test @ http://127.0.0.1:8083/hello/100
  16 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   103.56ms    1.86ms 111.58ms   61.71%
    Req/Sec    58.10      4.85    89.00     97.53%
  Latency Distribution
     50%  103.27ms
     75%  104.96ms
     90%  106.20ms
     99%  107.56ms
  55584 requests in 1.00m, 5.72MB read
Requests/sec:    925.17
Transfer/sec:     97.58KB

Install wrk on ubuntu system
https://github.com/wg/wrk/wiki/Installing-Wrk-on-Linux

> sudo apt-get install build-essential libssl-dev git -y
> git clone https://github.com/wg/wrk.git wrk
> cd wrk/
> make
> sudo cp wrk /usr/local/bin

On ubuntu, no socket issue, I split the test server and the host server into 2 machines and I run the tests again

> wrk -t4 -c1000 -d60s --timeout 10s http://10.3.10.96:8081/hello/100 --latency
Running 1m test @ http://10.3.10.96:8081/hello/100
  4 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   650.34ms  220.08ms   3.04s    79.55%
    Req/Sec   384.93     99.62     0.89k    68.29%
  Latency Distribution
     50%  615.78ms
     75%  794.01ms
     90%  900.03ms
     99%    1.17s
  90984 requests in 1.00m, 13.54MB read
Requests/sec:   1514.54
Transfer/sec:    230.73KB

Here is some key point in the sample Projects.
For Tomcat Servlet some key points in configuration and Java Codes
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath />
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

@Api(value = "/hello/")
@RestController
public class HelloController {
@ApiOperation(value = "hello latency", response = String.class)
@GetMapping("/hello/{latency}")
public String hello(@PathVariable long latency) {
try {
TimeUnit.MILLISECONDS.sleep(latency); // 1
} catch (InterruptedException e) {
return "Error during thread sleep";
}
return "Welcome to reactive world with latency " + latency ;
}
}

Jetty with Servlet 3.1
                <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-parser</artifactId>
<version>1.0.39</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>

@ApiOperation(value = "hello latency", response = String.class)
@GetMapping("/hello/{latency}")
public Mono<String> hello(@PathVariable int latency) {
return Mono.just("Welcome to reactive world " + latency).delayElement(Duration.ofMillis(latency));
}
@GetMapping("/go/{latency}")
public Mono<String> go(@PathVariable int latency) {
Mono<String> mono = Mono.fromCallable(() -> {
try {
Thread.sleep(latency);
} catch (InterruptedException e) {
e.printStackTrace();
}
return String.format("processing nonblocking %s", latency);
});
return mono.subscribeOn(Schedulers.elastic());
}
@GetMapping("/slow/{latency}")
public Mono<String> slow(@PathVariable int latency) {
try {
Thread.sleep(latency);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Mono.just("Welcome to reactive world " + latency);
}

Reactor Netty
                <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
@GetMapping("/hello/{latency}")
public Mono<String> hello(@PathVariable int latency) {
return Mono.just("Welcome to reactive world " + latency).delayElement(Duration.ofMillis(latency));
}
@GetMapping("/go/{latency}")
public Mono<String> go(@PathVariable int latency) {
Mono<String> mono = Mono.fromCallable(() -> {
try {
Thread.sleep(latency);
} catch (InterruptedException e) {
e.printStackTrace();
}
return String.format("processing nonblocking %s", latency);
});
return mono.subscribeOn(Schedulers.elastic());
}
@GetMapping("/slow/{latency}")
public Mono<String> slow(@PathVariable int latency) {
try {
Thread.sleep(latency);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Mono.just("Welcome to reactive world " + latency);
}


Related URLs for all my sample projects
Servlet API under Tomcat
http://localhost:8081/hello/1000
http://localhost:8081/swagger-ui.html#/hello-controller
http://localhost:8081/actuator

Jetty with Servlet 3.1
http://localhost:8082/hello/1000
http://localhost:8082/swagger-ui.html#/hello-controller
http://localhost:8082/actuator

Reactor Netty
http://localhost:8083/hello/1000
http://localhost:8083/actuator
http://localhost:8083/go/1000    (Wrap Sync Blocking Method)
http://localhost:8083/slow/1000   (Sync Blocking Method in Side Controller)


References:
Summary
https://blog.51cto.com/liukang/2090163

https://blog.lovezhy.cc/2018/12/29/webflux%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/
https://www.jianshu.com/p/7ee89f70dfe5
https://blog.51cto.com/liukang/2090183
https://blog.51cto.com/liukang/2090202

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html

Gatling test
https://blog.51cto.com/liukang/2090202
https://github.com/gatling/gatling-sbt-plugin-demo
https://github.com/luohuazju/sillycat-gatling

Web flux
https://blog.51cto.com/liukang/2090198



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics