第 17 章 配置 Web 服务器(Undertow)

17.1. Undertow 子系统概述

重要

在 JBoss EAP 7 里,undertow 取代了之前 JBoss EAP 版本里的 web 子系统。

undertow 子系统允许您配置 Web 服务器和 Servlet 容器设置。它实现了 Java Servlet 3.1 规格以及 Websocket 并支持 HTTP Upgrade,而且在 Servlet 部署里使用了高性能的非阻塞式处理程序。undertow 子系统也能够充当支持 mod_cluster 的高性能反向代理。

undertow 子系统里要配置 5 个主要的组件:

注意

虽然 JBoss EAP 提供了升级这些组件的配置的能力,默认的配置还是适用于多数情况且提供了合理的性能设置。

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  <buffer-cache name="default"/>
  <server name="default-server">
      <http-listener name="default" socket-binding="http" redirect-socket="https"/>
      <host name="default-host" alias="localhost">
          <location name="/" handler="welcome-content"/>
          <filter-ref name="server-header"/>
          <filter-ref name="x-powered-by-header"/>
      </host>
  </server>
  <servlet-container name="default">
      <jsp-config/>
      <websockets/>
  </servlet-container>
  <handlers>
      <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
  </handlers>
  <filters>
      <response-header name="server-header" header-name="Server" header-value="JBoss-EAP/7"/>
      <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
  </filters>
</subsystem>
重要

undertow 子系统也依赖 io 子系统来提供 XNIO 工作节点和缓冲池。io 子系统是单独配置的,它提供了在多数情况下应该展现优化性能的默认配置。

注意

和之前的 JBoss EAP 版本里的 web 子系统相比,JBoss EAP 7 里的 undertow 子系统有不同的 HTTP 方法的默认行为

17.2. 配置缓冲缓存

缓冲缓存(Buffer cache)被用来缓存静态资源。JBoss EAP 启用了部署可引用和配置的多个缓存,允许不同的部署使用不同的缓存大小。缓冲在区(region)中进行分配且大小固定。使用的总共空间可以通过缓冲大小乘以每个区的缓冲数量以及最大的区数量来计算。默认的缓冲缓存大小是 10MB。

JBoss EAP 默认提供单个缓存:

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  <buffer-cache name="default"/>
  ....
</subsystem>

更新现有的缓冲缓存

要更新现有的缓冲缓存:

/subsystem=undertow/buffer-cache=default/:write-attribute(name=buffer-size,value=2048)
重新载入

创建新的缓冲缓存

要创建新的缓冲缓存:

/subsystem=undertow/buffer-cache=new-buffer:add

删除缓冲缓存

要删除缓冲缓存:

/subsystem=undertow/buffer-cache=new-buffer:remove
重新载入

关于缓冲缓存的可配置属性的完整列表,请参考 Undertow 子系统属性章节。

17.3. 配置服务器

服务器代表一个 Undertow 实例并由几个元素组成:

  • host
  • http-listener
  • https-listener
  • ajp-listener

host 元素提供虚拟主机配置,而三个 listener 元素则提供到 Undertow 实例的不同类型的连接。

注意

您可以配置多个服务器,从而允许部署和服务器完全隔离。在某些情况下,如多租户环境里,这很有用。

JBoss EAP 默认提供单个服务:

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  <buffer-cache name="default"/>
  <server name="default-server">
      <http-listener name="default" socket-binding="http" redirect-socket="https"/>
      <host name="default-host" alias="localhost">
          <location name="/" handler="welcome-content"/>
          <filter-ref name="server-header"/>
          <filter-ref name="x-powered-by-header"/>
      </host>
  </server>
  ...
</subsystem>

更新现有的服务器

要更新现有的服务器:

/subsystem=undertow/server=default-server:write-attribute(name=default-host,value=default-host)
重新载入

创建新的服务器

要创建新的服务器

/subsystem=undertow/server=new-server:add
重新载入

删除服务器

要删除服务器:

/subsystem=undertow/server=new-server:remove
重新载入

关于服务器的可配置属性的完整列表,请参考 Undertow 子系统属性章节。

17.4. 配置 Servlet 容器

Servlet 容器提供所有 servlet、JSP 和 Websocket 相关的配置,包括和会话相关的配置。虽然多数服务器只需要单个的 Servlet 容器,您也可以添加额外的 servlet-container 元素来配置多个 Servlet 容器。使用多个 Servlet 容器可以把多个部署部署至不同虚拟主机的相同上下文路径上。

注意

Servlet 容器提供的多数配置都可以被部署应用程序的 web.xml 文件单独覆盖。

JBoss EAP 默认提供了一个 Servlet 容器:

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  <buffer-cache name="default"/>
  <server name="default-server">
    ...
  </server>
  <servlet-container name="default">
      <jsp-config/>
      <websockets/>
  </servlet-container>
...
</subsystem>

更新现有的 Servlet 容器

更新现有的 Servlet 容器:

/subsystem=undertow/servlet-container=default:write-attribute(name=ignore-flush,value=true)
重新载入

创建新的 Servlet 容器

创建新的 Servlet 容器:

/subsystem=undertow/servlet-container=new-servlet-container:add
重新载入

删除 Servlet 容器

删除 Servlet 容器:

/subsystem=undertow/servlet-container=new-servlet-container:remove
重新载入

关于 Servlet 容器的可配置属性的完整列表,请参考 Undertow 子系统属性章节。

17.5. 配置处理程序

JBoss EAP 允许配置两种类型的处理程序:

  • 文件处理程序
  • reverse-proxy 处理程序

文件处理程序服务静态文件。每个文件处理程序必须附加到虚拟主机里的某个位置。Reverse-proxy 处理程序允许 JBoss EAP 充当高性能的反向代理。它可以处理 AJP、HTTP 和 HTTP.2 后台并支持 mod_cluster。

JBoss EAP 默认提供了一个文件处理程序:

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  <buffer-cache name="default"/>
  <server name="default-server">
      ...
  </server>
  <servlet-container name="default">
      ...
  </servlet-container>
  <handlers>
      <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
  </handlers>
  ...
</subsystem>

对静态资源使用 WebDAV

之前的 JBoss EAP 版本允许将 WebDAV 和 web 子系统一起使用(WebdavServlet)来容纳静态资源,并启用额外的 HTTP 方法以访问和操作这些文件。在 JBoss EAP 7 里,undertow 子系统提供了通过文件处理程序服务静态文件的机制。但 undertow 子系统不支持 WebDAV。如果您想在 JBoss EAP 7 里使用 WebDAV,可以编写自定义的 WebDAV servlet。

更新现有的文件处理程序

更新现有的文件处理程序:

/subsystem=undertow/configuration=handler/file=welcome-content:write-attribute(name=case-sensitive,value=true)
重新载入

创建新的文件处理程序

创建新的文件处理程序:

/subsystem=undertow/configuration=handler/file=new-file-handler:add

删除文件处理程序

删除文件处理程序

/subsystem=undertow/configuration=handler/file=new-file-handler:remove
重新载入

关于处理程序的可配置属性的完整列表,请参考 Undertow 子系统属性章节。

17.6. 配置过滤器

过滤器可以修改请求的某些方面,且可以使用 predicate 来控制过滤器何时执行。过滤器的常见用例包括:设置头数据、进行 GZIP 压缩。

注意

过滤器从功能上来说等同于之前的 JBoss EAP 版本里使用的全局阀(Valve)。

您可以定义下列过滤器类型:

  • custom-filter
  • error-page
  • expression-filter
  • gzip
  • mod-cluster
  • request-limit
  • response-header
  • rewrite

JBoss EAP 默认提供两个过滤器:

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  <buffer-cache name="default"/>
  <server name="default-server">
    ...
  </server>
  <servlet-container name="default">
    ...
  </servlet-container>
  <handlers>
      ...
  </handlers>
  <filters>
      <response-header name="server-header" header-name="Server" header-value="JBoss-EAP/7"/>
      <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
  </filters>
</subsystem>

更新现有的过滤器

要更新现有的过滤器:

/subsystem=undertow/configuration=filter/response-header=server-header:write-attribute(name=header-value,value="JBoss-EAP")
重新载入

创建新的过滤器

要创建新的过滤器:

/subsystem=undertow/configuration=filter/response-header=new-response-header:add(header-name=new-response-header,header-value="My Value")

删除过滤器

要删除过滤器:

/subsystem=undertow/configuration=filter/response-header=new-response-header:remove
重新载入

关于过滤器的可配置属性的完整列表,请参考 Undertow 子系统属性章节。

17.7. 配置默认的 Welcome Web 应用程序

JBoss EAP 包含一个默认的 Welcome 应用程序,它默认显示在端口 8080 的根上下文里。

在 Undertow 里预配置了一个默认的服务器来提供欢迎内容。

默认的 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:3.1">
  ...
  <server name="default-server">
      <http-listener name="default" socket-binding="http" redirect-socket="https"/>
      <host name="default-host" alias="localhost">
          <location name="/" handler="welcome-content"/>
          <filter-ref name="server-header"/>
          <filter-ref name="x-powered-by-header"/>
      </host>
  </server>
  ...
  <handlers>
      <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
  </handlers>
  ...
</subsystem>

默认的服务器(default-server)配置了一个默认的主机(default-host)。这个默认的主机用 <location> 元素和 welcome-content 文件处理程序处理到服务器根目录的请求。welcome-content 处理程序在 path 属性指定的位置上提供内容。

您可以用自己的 Web 应用程序替换默认的 Welcome 应用程序。这可以用下列两种方法之一来配置:

您也可以禁用欢迎内容

修改 welcome-content 文件处理程序

修改现有的 welcome-content 文件处理程序的路径来指向新的部署。

/subsystem=undertow/configuration=handler/file=welcome-content:write-attribute(name=path,value="/path/to/content")
注意

或者,您可以创建一个服务器根目录使用的不同文件处理程序。

/subsystem=undertow/configuration=handler/file=NEW_FILE_HANDLER:add(path="/path/to/content")
/subsystem=undertow/server=default-server/host=default-host/location=\/:write-attribute(name=handler,value=NEW_FILE_HANDLER)

重新载入服务器来使所做的修改生效。

重新载入

修改 default-web-module

映射部署的 Web 应用程序至服务器的根目录。

/subsystem=undertow/server=default-server/host=default-host:write-attribute(name=default-web-module,value=hello.war)

重新载入服务器来使所做的修改生效。

重新载入

禁用默认的 Welcome Web 应用程序

通过删除 default-hostlocation 条目(/)来禁用欢迎应用程序。

/subsystem=undertow/server=default-server/host=default-host/location=\/:remove

重新载入服务器来使所做的修改生效。

重新载入

17.8. 配置 HTTPS

关于配置 HTTPS 用于 Web 应用程序以及管理接口的更多信息,请参考如何配置服务器安全性

17.9. 配置 HTTP 会话超时

HTTP 会话超时定义声明 HTTP 会话无效所需的失效时间。例如,用户访问部署在 JBoss EAP 里并创建 HTTP 会话的应用程序。如果这个用户在 HTTP 会话超时后试图再次访问该应用程序,原来的 HTTP 会话将失效,而用户将被迫创建一个新的 HTTP 会话。这可能导致非持久性数据的丢失或必须进行重新验证。

HTTP 超时会话是在应用程序的 web.xml 文件里配置的,但默认的 HTTP 会话超时可以在 JBoss EAP 里指定。服务器的超时值将适用于所有部署的应用程序,但应用程序的 web.xml 将覆盖服务器的值。

服务器的值是在 default-session-timeout 属性里指定的,它位于 undertow 子系统的 servlet-container 部分。default-session-timeout 的单位是分钟,默认值是 30。

配置默认的会话超时

要配置 default-session-timeout

/subsystem=undertow/servlet-container=default:write-attribute(name=default-session-timeout, value=60)
重新载入
重要

修改 HTTP 会话超时要求所有受影响的 JBoss EAP 实例重启。在重启完全之前,仍将应用原始的 HTTP 会话超时。

17.10. 配置 HTTP-Only 会话管理 Cookie

会话管理 Cookie 可以通过 HTTP API 和非 HTTP API(如 JavaScript)访问。JBoss EAP 提供将HttpOnly 头部作为 Set-Cookie 响应头部的一部分发送给客户(通常是浏览器)的能力。在被支持的浏览器里,启用这个头部告诉浏览器它应该防止通过非 HTTP API 来访问会话管理 Cookie。限制会话管理 Cookie 至 HTTP API 有助于减轻通过跨站点脚本攻击窃取会话 Cookie 的威胁。要启用这个行为,http-only 属性应该被设置为 true

重要

使用 HttpOnly 头部自身无法实际防止跨站点脚本攻击,它仅仅是通知浏览器而已。浏览器也必须支持 HttpOnly 以使这个行为生效。

重要

使用 http-only 属性仅将这个限制应用到会话管理 Cookie 而不是其他的浏览器 Cookie。

http-only 属性在 undertow 子系统的两个地方进行设置:

  • 在 Servlet 容器里作为会话 Cookie 设置
  • 在服务器的主机设置部分作为单点登录属性

要为 Servlet 容器会话 Cookie 配置 host-only 属性:

/subsystem=undertow/servlet-container=default/setting=session-cookie:add
/subsystem=undertow/servlet-container=default/setting=session-cookie:write-attribute(name=http-only,value=true)
重新载入

为主机单点登录配置 host-only

要为主机单点登录配置 host-only

/subsystem=undertow/server=default-server/host=default-host/setting=single-sign-on:add
/subsystem=undertow/server=default-server/host=default-host/setting=single-sign-on:write-attribute(name=http-only,value=true)
重新载入

17.11. 配置 HTTP/2

Undertow 允许使用 HTTP/2 标准,这通过压缩头部和在相同的 TCP 连接上多路传输多个数据流来减少延迟。它也为服务器提供了,在客户请求资源前将资源主动推送至客户端的能力,从而可以提高页面加载的速度。Undertow 也与 HTTP/2 以前的 SPDY 相兼容,因此可以支持没有更新至新规格的客户端。

重要

在 JBoss EAP 7.0 里 HTTP/2 仅作为技术预览支持,它只能用于支持 HTTP/2 标准的浏览器里。

重要

HTTP/2 不但需要使用 Java 8,而且还需要在 Casspath 上设立 ALPN。这是因为 HTTP/2 需要支持 ALPN 的 TLS 栈,而 Java 8 的默认安装是不提供的。

17.11.1. 配置 Undertow 来使用 HTTP/2

要配置 Undertow 使用 HTTP/2,请完成下列步骤:

配置 Undertow 使用 HTTPS

关于配置 Undertow 将 HTTPS 用于 Web 应用程序,请参考如何配置服务器的安全性

注意

换句话说,使用 HTTP/2 时不需要 HTTPS ,只要使用 HTTP Upgrade 的普通 HTTP 就可以了。此时,您不需要安装 ALPN,只要在 Undertow 里简单地启用 HTTP/2:

/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=enable-http2,value=true)
下载 ALPN JAR

首先确定 Java 的具体版本。从终端运行下列命令来查看 Java 的版本:

java -version

根据您的版本,请访问这个页面来确定从这个页面下载正确的 ALPN JAR 版本。例如,如果您运行的是 Java 1.8.0_51,您需要 ALPN 8.1.4.v20150727 并下载 alpn-boot-8.1.4.v20150727.jar

把 ALPN JAR 添加到 boot Classpath

在下载了正确的 ALPN JAR 版本后,请将其复制到 EAP_HOME/bin。您也必须添加下列内容至 bin/standalone.conf(如果运行在受管域里则是 bin/domain.conf),并用合适的值替换 $JBOSS_HOME$ALPN_VERSION

JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/p:$JBOSS_HOME/bin/alpn-boot-$ALPN_VERSION.jar"
重要

您必须重启 JBoss EAP 以使 classpath 的修改生效。

在 HTTPS Listener 启用 HTTP/2

要在 Undertow 里启用 HTTPS Listener 来使用 HTTP/2,需要把 enable-http2 属性设置为 true

/subsystem=undertow/server=default-server/https-listener=https:write-attribute(name=enable-http2,value=true)
检验 HTTP/2 是否被使用

要检验 Undertow 是否在使用 HTTP/2,您需要检查来自 Undertow 的头部信息。用 HTTPS 访问您的 JBoss EAP 实例,例如 https://localhost:8443,并使用您的浏览器的开发人员工具来检查头部信息。某些浏览器,如 Google Chrome,在使用 HTTP/2 时将显示 HTTP/2 伪头部信息(:path:authority, :method:scheme),而其他浏览器(如 Firefox 和 Safari)将会报告头部的状态或版本为 HTTP/2.0

17.12. 配置 RequestDumping 处理程序

RequestDumping 处理程序(io.undertow.server.handlers.RequestDumpingHandler)登记 JBoss EAP 里 Undertow 处理的请求,以及相关的响应对象的细节。

重要

虽然这个处理程序可用于调试,但它可能也会记录下敏感信息。因此,在启用这个处理程序时请记住这一点。

注意

RequestDumping 处理程序替代了之前的 JBoss EAP 版本里的 RequestDumperValve

您可以直接在服务器级别或单独的应用程序里配置 RequestDumping 处理程序。

17.12.1. 配置服务器上的 RequestDumping 处理程序

RequestDumping 处理程序应该配置为表达式过滤器。要将 RequestDumping 处理程序配置为表达式过滤器,您需要:

RequestDumping 处理程序创建一个新的表达式过滤器
/subsystem=undertow/configuration=filter/expression-filter=requestDumperExpression:add(expression="dump-request")
在 Undertow Web Server 里启用表达式过滤器
/subsystem=undertow/server=default-server/host=default-host/filter-ref=requestDumperExpression:add
重要

以这种方式将 RequestDumping 启用为表达过滤器时,Undertow Web Server 处理的所有请求和对应的响应将被记录。

为特定的 URL 配置 RequestDumping 处理程序

除了记录所有请求以外,您也可以使用表达式过滤器来记录特定 URL 的请求和对应的响应。这可以通过在表达式使用 predicate 来实现,如 pathpath-prefixpath-suffix。例如,如果您想记录所有的请求和对应的响应至 /myApplication/test,在创建表达式过滤器时您可以使用表达式 "path(/myApplication/test) -> dump-request" 而不是 "dump-request"。这将带有完全匹配 /myApplication/test 路径的请求指引至 RequestDumping 处理程序。

17.12.2. 在应用程序里配置 RequestDumping 处理程序

除了在服务器里配置 RequestDumping 处理程序,您还可以在单独的应用程序里配置它。这将限制处理程序的作用域至特定的应用程序。RequestDumping 处理程序应该在 WEB-INF/undertow-handlers.conf 里进行配置。

要在 WEB-INF/undertow-handlers.conf 里配置 RequestDumping 处理程序以记录这个应用程序的所有请求和对应的响应,请添加下列表达式至 WEB-INF/undertow-handlers.conf

WEB-INF/undertow-handlers.conf 示例

dump-request

要在 WEB-INF/undertow-handlers.conf 里配置 RequestDumping 应用程序来记录这个应用程序里特定 URL 的请求和响应,您可以在表达式里使用 predicate,如 pathpath-prefixpath-suffix。例如,要记录所有的请求和对应的响应至您的应用程序里的 test,您可以使用下列带有 path predicate 的表达式:

WEB-INF/undertow-handlers.conf 示例

path(/test) -> dump-request

注意

当在应用程序的WEB-INF/undertow-handlers.conf 里定义的表达式里使用 pathpath-prefixpath-suffix 等 predicate 时,所有的值将和应用程序的根上下文相关。例如,如果应用程序的根上下文是 myApplication 并在 WEB-INF/undertow-handlers.conf 里配置了表达式 path(/test) -> dump-request,它只会记录请求和对应的响应至 /myApplication/test