17.4. 配置服务器

服务器代表 Undertow 的实例,由多个元素组成:

  • 主机
  • http-listener
  • https-listener
  • ajp-listener

主机元素提供虚拟主机配置,而三个侦听器则将该类型的连接提供给 Undertow 实例。

服务器的默认行为是在服务器启动时对请求进行队列。您可以使用主机上的 queue-requests-on-start 属性来更改默认行为。如果此属性设为 true (默认值),则服务器启动时到达的请求将被保留,直到服务器就绪为止。如果此属性设为 false,则在服务器完全启动前到达的请求将通过默认响应代码被拒绝。

无论属性值是什么,在服务器完全启动前请求处理不会启动。

您可以使用管理控制台配置 queue-requests-on-start 属性,方法是导航到 ConfigurationSubsystemsWeb(Undertow)Server,选择服务器并点击 View,然后选择 Hosts 选项卡。对于受管域,您必须指定要配置的配置文件。

注意

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

JBoss EAP 默认提供一个服务器:

默认 Undertow 子系统配置

<subsystem xmlns="urn:jboss:domain:undertow:10.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other">
    <buffer-cache name="default"/>
    <server name="default-server">
        <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
        <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
        <host name="default-host" alias="localhost">
            <location name="/" handler="welcome-content"/>
            <http-invoker security-realm="ApplicationRealm"/>
        </host>
    </server>
    ...
</subsystem>

以下示例演示了如何使用管理 CLI 配置服务器。您还可以通过导航到 ConfigurationSubsystemsWeb(Undertow)Server,使用管理控制台配置服务器

更新现有服务器

更新现有服务器:

/subsystem=undertow/server=default-server:write-attribute(name=default-host,value=default-host)
reload

创建新服务器

创建新服务器:

/subsystem=undertow/server=new-server:add
reload

删除服务器

删除服务器:

/subsystem=undertow/server=new-server:remove
reload

有关可用于配置服务器的属性的完整列表,请参阅 Undertow Subsystem Attributes 部分。

17.4.1. 访问日志记录

您可以在您定义的每个主机上配置访问日志。

有两个可用的访问日志记录选项:标准访问日志和控制台访问日志。

请注意,访问日志记录所需的额外处理可能会影响系统性能。

17.4.1.1. 标准访问日志

标准访问日志将日志条目写入到日志文件。

默认情况下,日志文件存储在 standalone/log/access_log.log 目录中。

要启用标准访问日志,请将 access-log 设置添加到您要捕获访问日志数据的主机。以下 CLI 命令演示了默认 JBoss EAP 服务器中默认主机上的配置:

/subsystem=undertow/server=default-server/host=default-host/setting=access-log:add
注意

您必须在启用标准访问日志记录后重新加载服务器。

默认情况下,访问日志记录包括以下数据:

  • 远程主机名
  • 远程逻辑用户名(always -)
  • 经过身份验证的远程用户
  • 请求的日期和时间,格式为通用日志格式
  • 请求的第一行
  • 响应的 HTTP 状态代码
  • 发送的字节数,HTTP 标头除外

这组数据被定义为常见模式。也提供另一种组合模式。除了常见模式中记录的数据外,组合模式还包括来自传入标头的引用者和用户代理。

您可以使用 pattern 属性更改记录的数据。以下 CLI 命令演示了更新 pattern 属性以使用组合模式:

/subsystem=undertow/server=default-server/host=default-host/setting=access-log:write-attribute(name=pattern,value="combined"
注意

您必须在更新 pattern 属性后重新加载服务器。

表 17.1. 可用模式

pattern描述

%a

远程 IP 地址

%A

本地 IP 地址

%b

发送字节,除 HTTP 标头或 - 如果没有发送字节

%B

发送的字节数,HTTP 标头除外

%h

远程主机名

%H

请求协议

%l

远程逻辑用户名 from identd (始终返回 - ;为 Apache 访问日志兼容性而包含)

%m

请求方法

%p

本地端口

%q

查询字符串(除 ? 字符外)

%r

请求的第一行

%s

响应的 HTTP 状态代码

%t

日期和时间,采用通用日志格式格式

%u

经过身份验证的远程用户

%U

请求的 URL 路径

%v

本地服务器名称

%D

处理请求所需的时间,以毫秒为单位

%T

处理请求的时间(以秒为单位)

%I

当前 Request 线程名称(稍后与堆栈追踪进行比较)

common

%h %l %u %t "%r" %s %b

combined

%h %l %u %t "%r" %s %b "%{i,Referer}" "%{i,User-Agent}"

您还可以从 Cookie、传入的标头和响应标头或会话中写入信息。该语法采用 Apache 语法建模:

  • 用于传入标头的 %{I,xx}
  • 用于传出响应标头的 %{O,xxx}
  • 特定 Cookie %{C,xxx}
  • %{R,xxx} where xxxServletRequest中的属性
  • %{s,xxx} where xxxHttpSession中的属性

此日志提供了其他配置选项。如需更多信息,请参阅附录中的"访问日志属性"。

17.4.1.2. 控制台访问日志

控制台访问日志将数据写入 stdout,结构为 JSON 数据。

每个访问记录都是一行数据。您可以捕获此数据以供日志聚合系统处理。

要配置控制台访问日志,请向要捕获访问日志数据的主机添加 console-access-log 设置。以下 CLI 命令演示了默认 JBoss EAP 服务器中默认主机上的配置:

/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:add

默认情况下,控制台访问日志记录包括以下数据:

表 17.2. 默认控制台访问日志数据

日志数据字段名称描述

eventSource

请求中事件的源

hostName

处理请求的 JBoss EAP 主机

bytesSent

JBoss EAP 服务器响应请求而发送的字节数

dateTime

JBoss EAP 服务器处理请求的日期和时间

remoteHost

请求源自的机器的 IP 地址

remoteUser

与远程请求关联的用户名

requestLine

已提交请求

responseCode

JBoss EAP 服务器返回的 HTTP 响应代码

日志输出中始终包含默认属性。您可以使用 properties 属性 来更改默认日志数据的标签,在某些情况下,也可更改数据配置。您还可以使用 properties 属性 向输出中添加额外的日志数据。

表 17.3. 可用的控制台访问日志数据

日志数据字段名称描述格式

authentication-type

用于验证与请求关联的用户的身份验证类型。Default label: authenticationType 使用 key 选项更改此属性的标签。

authentication-type{} authentication-type={key="authType"}

bytes-sent

请求返回的字节数,不包括 HTTP 标头。默认标签:bytesSent 使用 key 选项更改此属性的标签。

bytes-sent={} bytes-sent={key="sent-bytes"}

date-time

接收和处理请求的日期和时间。默认标签:dateTime 使用 key 选项更改此属性的标签。使用 date-format 定义用于格式化日期记录的模式。模式必须是 Java SimpleDateFormatter 模式。使用 time-zone 选项指定要格式化 date-format 选项时用于格式化日期和/或时间数据的时区。此值必须是有效的 java.util.TimeZone。

date-time={key="<keyname>", date-format="<date-time format>"} date-time={key="@timestamp", date-format="yyyy-MM-dd'T'H:mm:ssSSS"}

host-and-port

请求查询的主机和端口。默认标签:hostAndPort 使用 key 选项更改此属性的标签。

host-and-port{} host-and-port={key="port-host"}

local-ip

本地连接的 IP 地址。使用 key 选项更改此属性的标签。默认标签:localIp 使用 key 选项更改此属性的标签。

local-ip{} local-ip{key=”localIP”}

local-port

本地连接的端口。默认标签:localPort 使用 key 选项更改此属性的标签。

local-port{} local-port{key=”LocalPort”}

local-server-name

处理请求的本地服务器的名称。默认标签:localServerName 使用 key 选项更改此属性的标签。

local-server-name {} local-server-name {key=LocalServerName}

path-parameter

请求中包含的一个或多个路径或 URI 参数。name 属性是一个用逗号分开的名称列表,用于解析交换值。使用 key-prefix 属性使键唯一。如果指定了 key-prefix,则前缀前面是输出中每个路径参数的名称的前面。

path-parameter{names={store,section}} path-parameter{names={store,section}, key-prefix="my-"}

predicate

predicate 上下文的名称。name 属性是一个用逗号分开的名称列表,用于解析交换值。使用 key-prefix 属性使键唯一。如果指定了 key-prefix,则前缀前面是输出中每个路径参数的名称的前面。

predicate{names={store,section}} predicate{names={store,section}, key-prefix="my-"}

query-parameter

请求中包含的一个或多个查询参数。name 属性是一个用逗号分开的名称列表,用于解析交换值。使用 key-prefix 属性使键唯一。如果指定了 key-prefix,则前缀前面是输出中每个路径参数的名称的前面。

query-parameter{names={store,section}} query-parameter{names={store,section}, key-prefix="my-"}

query-string

请求的查询字符串。默认标签:queryString 使用键选项更改此属性的标签。使用 include-question-mark 属性指定查询字符串是否应包含问标记。默认情况下不包含问号。

query-string{} query-string{key=”QueryString”, include-question-mark=”true”}

relative-path

请求的相对路径。默认标签: relativePath 使用 key 选项更改此属性的标签。

relative-path{} relative-path{key=”RelativePath”}

remote-host

远程主机名。默认标签:remoteHost 使用 key 选项更改此属性的标签。

remote-host{} remote-host{key=”RemoteHost”}

remote-ip

远程 IP 地址。默认标签:remoteIp 使用键选项更改此属性的标签。使用模糊的属性,模糊处理输出日志记录中的 IP 地址。默认值为 false。

remote-ip{} remote-ip{key=”RemoteIP”, obfuscated=”true”}

remote-user

经过身份验证的远程用户.默认标签:remoteUser 使用密钥选项更改此属性的标签。

remote-user{} remote-user{key=”RemoteUser”}

request-header

请求标头的名称。结构化数据的键是标头的名称;值是已命名标头的值。name 属性是一个用逗号分开的名称列表,用于解析交换值。使用 key-prefix 属性使键唯一。如果指定了 key-prefix,则该前缀前面是日志输出中请求标头名称的前面。

request-header{names={store,section}} request-header{names={store,section}, key-prefix="my-"}

request-line

请求行。默认标签: requestLine 使用 key 选项更改此属性的标签。

request-line{} request-line{key="Request-Line"}

request-method

请求方法。默认 label: requestMethod 使用 key 选项更改此属性的标签。

request-method{} request-method{key="RequestMethod"}

request-path

请求的相对路径。默认 label: requestPath 使用 key 选项更改此属性的标签。

request-path{} request-path{key=”RequestPath”}

request-protocol

请求的协议。默认标签:requestProtocol 使用 key 选项更改此属性的标签。

request-protocol{} request-protocol{key="RequestProtocol"}

request-scheme

请求的 URI 架构。默认 label: requestScheme 使用 key 选项更改此属性的标签。

request-scheme{} request-scheme{key=”RequestScheme”}

request-url

原始请求 URI。如果客户端指定,包括主机名、协议等。默认 label: requestUrl 使用 key 选项更改此属性的标签。

request-url{} request-url{key="RequestURL"}

resolved-path

解析路径.Default Label: resolvedPath 使用 key 选项更改此属性的标签。

resolved-path{} resolved-path{key=”ResolvedPath”}

response-code

响应代码。默认 label: responseCode 使用 key 选项更改此属性的标签。

response-code{} response-code{key=”ResponseCode”}

response-header

响应标头的名称。结构化数据的键是标头的名称;值是已命名标头的值。name 属性是一个用逗号分开的名称列表,用于解析交换值。使用 key-prefix 属性使键唯一。如果指定了 key-prefix,则该前缀前面是日志输出中请求标头名称的前面。

response-header{names={store,section}} response-header{names={store,section}, key-prefix="my-"}

response-reason-phrase

响应代码的文本原因。默认标签:backendReasonPhrase 使用 key 选项更改此属性的标签。

response-reason-phrase{} response-reason-phrase{key=”ResponseReasonPhrase”}

response-time

用于处理请求的时间。Default label: responseTime 使用 key 选项更改此属性的标签。默认的时间单元是 MILLISECONDS。可用时间单元包括:* NANOSECONDS * MICROSECONDS * MILLISECONDS * SECONDS

response-time{} response-time{key=”ResponseTime”, time-unit=SECONDS}

secure-exchange

指明交换是否安全。默认标签: secureExchange 使用 key 选项更改此属性的标签。

secure-exchange{} secure-exchange{key=”SecureExchange”}

ssl-cipher

请求的 SSL 密码。默认标签:sslCipher 使用 key 选项更改此属性的标签。

ssl-cipher{} ssl-cipher{key=”SSLCipher”}

ssl-client-cert

请求的 SSL 客户端证书。默认标签:sslClientCert 使用 key 选项更改此属性的标签。

ssl-client-cert{} ssl-client-cert{key=”SSLClientCert”}

ssl-session-id

请求的 SSL 会话 ID。默认标签:sslSessionId 使用 key 选项更改此属性的标签。

SSL-session-id{} stored-response

存储的对请求的响应。默认 label:storageResponse 使用 key 选项更改此属性的标签。

stored-response{} stored-response{key=”StoredResponse”}

thread-name

当前线程的线程名称。默认 label: threadName 使用 key 选项更改此属性的标签。

thread-name{} thread-name{key=”ThreadName”}

transport-protocol

您可以使用 metadata 属性配置其他任意数据,以包含在访问日志记录中。metadata 属性的值是 一组 key:value 对,用于定义要在访问日志记录中包含的数据。对中的值可以是管理模型表达式。服务器启动或重新加载后,即可解决管理模型表达式。键值对用逗号分开。

以下 CLI 命令演示了复杂的控制台日志配置示例,包括附加日志数据、自定义日志数据和其他元数据:

/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:add(metadata={"@version"="1", "qualifiedHostName"=${jboss.qualified.host.name:unknown}}, attributes={bytes-sent={}, date-time={key="@timestamp", date-format="yyyy-MM-dd'T'HH:mm:ssSSS"}, remote-host={}, request-line={}, response-header={key-prefix="responseHeader", names=["Content-Type"]}, response-code={}, remote-user={}})

生成的访问日志记录类似于以下额外 JSON 数据(注:以下示例输出被格式化为可读性;实际记录中,所有数据将以一行形式输出):

{
    "eventSource":"web-access",
    "hostName":"default-host",
    "@version":"1",
    "qualifiedHostName":"localhost.localdomain",
    "bytesSent":1504,
    "@timestamp":"2019-05-02T11:57:37123",
    "remoteHost":"127.0.0.1",
    "remoteUser":null,
    "requestLine":"GET / HTTP/2.0",
    "responseCode":200,
    "responseHeaderContent-Type":"text/html"
}

以下命令演示了在激活控制台访问日志后对日志数据的更新:

/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:write-attribute(name=attributes,value={bytes-sent={}, date-time={key="@timestamp", date-format="yyyy-MM-dd'T'HH:mm:ssSSS"}, remote-host={}, request-line={}, response-header={key-prefix="responseHeader", names=["Content-Type"]}, response-code={}, remote-user={}})

以下命令演示了在激活控制台访问日志后自定义元数据的更新:

/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:write-attribute(name=metadata,value={"@version"="1", "qualifiedHostName"=${jboss.qualified.host.name:unknown}}