图解WildFly8之Servlet容器Undertow剖析

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: Undertow简介Undertow 是RedHat(红帽公司)的开源产品,采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。

Undertow简介

Undertow 是RedHat(红帽公司)的开源产品,采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。

WildFly8的默认Servlet容器采用的不是Tomcat,也不是Jetty,而是JBoss自己开源的Undertow,Undertow是用Java编写的性能灵活的Servlet容器,底层基于高性能的NIO框架XNIO,XNIO也是JBoss开源的产品,JBoss开源的高性能NIO框架还有一个很有名:Netty。Undertow在WildFly8中的角色如图:


Undertow的架构类似于Jetty,采用应用内嵌的方式,这也正是为什么说它有灵活的性能的原因,利用Undertow可以快速构建一个小巧的应用服务,实现代码如下:

import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.ServletContainer;
import io.undertow.servlet.api.ServletInfo;

public class WildFlyServer {

    public static void main(final String[] args) throws Exception {
        
        // 创建ServletInfo,名字"MyServlet"必须唯一
        ServletInfo servlet1 = Servlets.servlet("MyServlet", MyServlet.class);
        // 设置Servlet的init方法执行时需要的数据
        servlet1.addInitParam("message", "Hello World");
        // 绑定映射为/hello
        servlet1.addMapping("/hello");
        
        // 创建名字MessageServlet为的ServletInfo
        ServletInfo servlet2 = Servlets.servlet("MessageServlet", MessageServlet.class);
        servlet2.addInitParam("message", "MyServlet");
        // 绑定映射为/myservlet
        servlet2.addMapping("/qrcode");
        
        // 创建DeploymentInfo应用布署
        DeploymentInfo deployment = Servlets.deployment();
        // 指定ClassLoader
        deployment.setClassLoader(WildFlyServer.class.getClassLoader());
        // 应用上下文(必须与映射路径一致,否则sessionID会有问题,每次都新建)
        deployment.setContextPath("/myapp");
        // 设置布署包名
        deployment.setDeploymentName("test.war");
        // 添加ServletInfo
        deployment.addServlets(servlet1,servlet2);

        // 创建DeploymentInfo2应用布署
        DeploymentInfo deployment2 = Servlets.deployment();
        deployment2.setClassLoader(WildFlyServer.class.getClassLoader());
        deployment2.setContextPath("/myapp2");
        deployment2.setDeploymentName("test2.war");
        deployment2.addServlets(servlet1,servlet2);
        
        // 使用默认Servlet容器,并将布署添加至容器
        ServletContainer container = Servlets.defaultContainer();
        // 将布署添加至容器,生成布置对应的管理器
        DeploymentManager manager = container.addDeployment(deployment);
        DeploymentManager manager2 = container.addDeployment(deployment2);
        // 实施布署
        manager.deploy();
        manager2.deploy();
        
        // 生成路径处理器(作用是dispatch servlet),默认返回"/*"处理器
        PathHandler path = Handlers.path();
        // 生成路径处理器,返回"/*"自动重定向到"/myapp"的处理器
//        PathHandler path = Handlers.path(Handlers.redirect("/myapp"));
        
        // 启动容器,生成请求处理器
        HttpHandler myapp = manager.start();
        HttpHandler myapp2 = manager2.start();
        // 绑定映射关系
        path.addPrefixPath("/myapp", myapp);
        path.addPrefixPath("/myapp2", myapp2);
        
        Undertow server = Undertow.builder()
                // 绑定端口与主机
                .addHttpListener(8080, "localhost")
                // 设置分发处理器PathHandler
                .setHandler(path)
                .build();
        // 启动Server
        server.start();
        
    }
}

从源代码,我们可以抽象出Undertow生成应用的架构,如图所示


利用运行调试,我们可以更加深入地了解Undertow中的一些概念:
ServletInfo:Servlet的最小单位,是对javax.servlet.Servlet具体实现的再次封装

FilterInfo:过滤器封装
DeploymentInfo:包布署对象,包含多个ServletInfo,可以说是ServletInfo的集合
ServletContainer:容器,用来管理DeploymentInfo,一个容器可以添加多个DeploymentInfo
DeploymentManager:包布署的管理,是对添加到ServletContainer的DeploymentInfo的一个引用,用于运行发布和启动容器
HttpHandler:servlet path处理器,DeploymentManager启动后返回的Servlet处理器,通常是HttpContinueReadHandler(连续读处理器)
PathHandler:分发器,将用户请求分发给对应的HttpHandler
HttpServerExchange:数据交换封装,可以转换成ServletRequest和ServletResponse
示例代码的调试运行栈如下:


连接通道


作为Servlet协议协议转换的实体HttpServerExchange的结构如下:


Undertow的性能

专业测评结果的数据如下:


目录
相关文章
|
4月前
|
Java 中间件 应用服务中间件
Servlet容器与Web容器详解
Servlet容器与Web容器详解
219 0
|
2月前
|
前端开发 Java 应用服务中间件
Spring Boot 2.x 嵌入式 Servlet 容器
Spring Boot使用内嵌Tomcat,默认端口8080,可通过`application.properties`配置端口、上下文路径等。配置方式有两种:1) 直接在配置文件中添加`server.port`和`server.servlet.context-path`;2) 创建`WebServerFactoryCustomizer` Bean来自定义配置,如设置端口`factory.setPort(8083)`,这种方式优先级更高。
|
3月前
|
Java 应用服务中间件 容器
手写SpringBoot(二)之动态切换Servlet容器
我们在切换serlvet容器的时候,会将SpringBoot默认的tomcat jar包给排除掉,换上我们需要的jar包,比如jetty。
30 0
|
11月前
|
Java 应用服务中间件 容器
25 SpringBoot使用外置的Servlet容器
25 SpringBoot使用外置的Servlet容器
43 0
|
11月前
|
前端开发 Java 应用服务中间件
24 SpringBoot配置嵌入式Servlet容器
24 SpringBoot配置嵌入式Servlet容器
63 0
24 SpringBoot配置嵌入式Servlet容器
|
Java 中间件 应用服务中间件
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
347 0
Web 容器、HTTP 服务器 、Servlet 容器区别与联系
|
设计模式 安全 Java
【Tomcat技术专题】循序渐进,分析Servlet容器鼻祖的Server和Service组件原理
【Tomcat技术专题】循序渐进,分析Servlet容器鼻祖的Server和Service组件原理
161 0
【Tomcat技术专题】循序渐进,分析Servlet容器鼻祖的Server和Service组件原理
|
14天前
|
弹性计算 运维 持续交付
探索Docker容器化技术及其在生产环境中的应用
探索Docker容器化技术及其在生产环境中的应用
64 5
|
6天前
|
Linux iOS开发 Docker
Docker:容器化技术的领航者 —— 从基础到实践的全面解析
在云计算与微服务架构日益盛行的今天,Docker作为容器化技术的佼佼者,正引领着一场软件开发与部署的革命。它不仅极大地提升了应用部署的灵活性与效率,还为持续集成/持续部署(CI/CD)提供了强有力的支撑。
173 69
|
7天前
|
运维 Cloud Native Docker
云原生技术入门:Docker容器化实战
【9月更文挑战第20天】本文将引导你走进云原生技术的世界,通过Docker容器化技术的实战演练,深入理解其背后的原理和应用。我们将一起探索如何在云平台上利用Docker简化部署、扩展和管理应用程序的过程,并揭示这一技术如何改变现代软件的开发和运维模式。