Spring Boot中嵌入式Servlet容器的比较

1. 介绍

随着云原生应用和微服务的流行也催生了对嵌入式Servlet容器需求的增长。为更加简单的构建应用和服务,Spring Boot为开发者提供了三种成熟的容器:Tomcat,Undertow和Jetty。

在本文中,我们会演示了一种方法:测量启动和增加负载时获取的指标来快速的比较不同容器实现的性能差异。

2. 依赖

首先我们在pom.xml中指定了spring-boot-starter-web 这个依赖,这是我们为我们每一个容器实现进行测量前所必须的具备。

通常的,我们会指定使用 spring-boot-starter-parent 作为我们的父依赖,然后接着加入我们需要的starter:

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.3.RELEASE</version>

<relativePath/>

</parent>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

</dependencies>

2.1 Tomcat

因为在我们spring-boot-starter-web在我们的依赖中,默认采用的是Tomcat容器,因此我们不需要再做更多的配置。

2.2 Jetty

为了使用Jetty,我们首先需要从spring-boot-starter-web中去掉spring-boot-starter-tomcat 这个依赖。

然后,我们只需要简单引入spring-boot-starter-jetty的依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

<exclusions>

<exclusion>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-tomcat</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jetty</artifactId>

</dependency>

2.3 Undertow

设置Undertow的方式和Jetty类似,不过去除依赖后,我们会使用spring-boot-starter-undertow 作为我们的依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

<exclusions>

<exclusion>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-tomcat</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-undertow</artifactId>

</dependency>

2.4 Actuator

我们使用Spring Boot的Actuator组件来对系统进行压力测试和查询应用指标。

你可以通过阅读这篇文章来更加详细的了解Actuator。本文中,我们只需要在pom中添加这个依赖:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-actuator</artifactId>

</dependency>

2.5 Apache Beach

Apache Bench是一个开源的负载测试工具,但它通常会和Apache Web 服务器捆绑在一起。

Windows用户可以点击此处进行下载。如果你的Windows电脑上已经有了这个工具,你应该可以在你的apache/bin 目录下找到ab.exe 。

如果你是Linux的用户,你可以通过apt-get命令来安装ab

$ apt-get install apache2-utils

3. 启动指标

3.1 搜集

为了搜集我们的启动指标,我们会在Spring Boot的ApplicationReadyEvent 注册我们关注的指标。

我们直接使用Actuator组件提供的MeterRegistry工具,通过编程的方式来直接获取我们所关注的指标:

@Component

public class StartupEventHandler {

// logger, constructor

private String[] METRICS = {

"jvm.memory.used",

"jvm.classes.loaded",

"jvm.threads.live"};

private String METRIC_MSG_FORMAT = "Startup Metric >> {}={}";

private MeterRegistry meterRegistry;

@EventListener

public void getAndLogStartupMetrics(

ApplicationReadyEvent event) {

Arrays.asList(METRICS)

.forEach(this::getAndLogActuatorMetric);

}

private void processMetric(String metric) {

Meter meter = meterRegistry.find(metric).meter();

Map<Statistic, Double> stats = getSamples(meter);

        logger.info(METRIC_MSG_FORMAT, metric, stats.get(Statistic.VALUE).longValue());

}

// other methods

}

为了避免人为的通过Actuator的REST端点进行性能指标的查询,我们启动一个独立的JMX进程来记录应用启动应用时我们所关注的指标数据。

3.2 选择

Actuator可以为我们提供了大量的指标数据。在应用启动后,我们选择了三个具有代表性的指标,他们可以展现系统运行时的关键点的概况。

jvm.memory.used JVM在启动后总共使用的内存量

jvm.classes.loaded JVM中总共加载的class文件的数量

jvm.threads.live JVM中存活的线程数量。在我们的测试中,这个值可以展现为处于"休息"状态的线程的数量。

4. 运行时指标

4.1 搜集

除了提供启动指标, 当我们启动Apache Bench后,使用Actuator组件提供的/metrics端点作为目标url进行请求,以使我们的应用处于负载阶段。

为了测试一个真实的处于负载的应用,我们可能更需要使用我们的应用系统所提供的端点进行测试。

一旦我们的应用启动完成,我们使用以下命令来启动并执行的ab:

ab -n 10000 -c 10 http://localhost:8080/actuator/metrics

4.2 选择

Apache Bench能够快速的给予我们一些有用的信息:包括连接时间,在某一段时间的请求的占比等。

为了我们的目的,我们通常更加关注每秒请求个数和每个请求的处理时间的均值。

5. 结果

在启动阶段,我们通过对Tomcat,Jetty和Undertow所占用内存的比较,我们发现Jetty占用的内存最小,Undertow次之,Tomcat最多。

在我们的测量中,我么还能发现Tomcat,Jetty和Undertow的性能比较:我们可以清楚的看到Undertow很明显是最快的,而Jetty则相对于慢一些。

MetricTomcatJettyUndertowjvm.memory.used (MB)168155164jvm.classes.loaded986997849787jvm.threads.live251719Requests per second154216271650Average time per request (ms)6.4836.1486.059

请注意,我们的这些指标都是在裸项目(没有添加任何业务代码的项目)下进行的测量。如果是自己的项目,那么测量指标大概率会有不同。

6. 基准测试讨论

开发适当的基准测试以充分测试容器实现的性能可能是相当复杂的。为了提取其中最关键的信息,能够清晰认识到要针对每个具体问题所编写出正确的测试案例是非常重要的。

值得注意的是,示例中使用了Actutor的HTTP GET请求作为负载,以此来收集的所需要指标的测量值。

可预见的是,不同的工作负载会导致对容器实现的进行不同指标的测量和搜集。如果需要更加健壮和精确的测量,建立一个更接近生产用例的测试计划是一个非常好的办法。

此外,更复杂的基准测试解决方案(如JMeter或Gatling)可能会得到更有价值的测试结论。

7. 选择容器

选择一个合适的容器实现应当要基于多方面的考量,而不能仅仅是基于一些硬性指标的概况就做出仓促的选择。适用性,特性,可配置性和策略通常也起到相当大的考量。

8. 结论

在本文中,我们看了Tomcat,Jetty和Undertow的嵌入式的Servlet容器的实现。我们通过Actuator暴露的metrics端点来测试了每一个Servlet容器在使用默认配置时的启动后的运行时指标。

我们通过使用Apache Bench来对应用进行压力测试,同时收集各项性能指标。

最后,我们谈论了这个策略的优势,并提及了当比较各个实现的基准时应当要熟记于心的几个建议。和往常一样,你可以从Github上获取项目中的所有源码。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容