15.4. 配置服务器
服务器代表 Undertow 实例,它由几个元素组成:
- 主机
- http-listener
- https-listener
- ajp-listener
host 元素提供虚拟主机配置,而三个监听器向 Undertow 实例提供该类型的连接。
服务器的默认行为是在服务器启动时排队请求。您可以使用主机上的 queue-requests-on-start
属性来更改默认行为。如果此属性设为 true
,这是默认设置,那么在服务器就绪前,到达服务器启动的时间的请求。如果此属性设为 false
,则在服务器完全启动前到达的请求将使用默认响应代码拒绝。
无论属性值如何,请求处理都不会启动,直到服务器完全启动为止。
您可以使用管理控制台配置 queue-requests-on-start
属性,导航到 Configuration
可以配置多个服务器,允许完全隔离部署和服务器。这在某些情况下(如多租户环境)非常有用。
JBoss EAP 默认提供服务器:
默认的 Undertow 子系统配置
<subsystem xmlns="{UndertowSubsystemNamespace}" 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 配置服务器。您还可以使用管理控制台配置服务器,方法是导航到 Configuration
更新现有服务器
更新现有服务器:
/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 子系统属性 部分。
15.4.1. 访问日志记录
您可以在您定义的每个主机上配置访问日志记录。
有两个访问日志记录选项可用:标准访问日志记录和控制台访问日志。
请注意,访问日志记录所需的额外处理可能会影响系统性能。
15.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
您必须在启用标准访问日志记录后重新载入服务器。
默认情况下,访问日志记录包括以下数据:
- 远程主机名
- 远程逻辑用户名(始终 -)
- 已验证的远程用户
- 请求的日期和时间,采用通用日志格式
- 请求的第一行
- 响应的 HTTP 状态代码
- 发送的字节数,不包括 HTTP 标头
这组数据被定义为通用模式。另外,还可使用另一个模式。除了以通用模式记录的数据外,组合模式还包括传入标头中的 referer 和 user 代理。
您可以使用 pattern
属性更改记录的数据。以下 CLI 命令演示了更新 pattern
属性以使用 combined 模式:
/subsystem=undertow/server=default-server/host=default-host/setting=access-log:write-attribute(name=pattern,value="combined"
在更新 pattern 属性后,您必须重新加载服务器。
pattern | 描述 |
---|---|
%a | 远程 IP 地址 |
%A | 本地 IP 地址 |
%b |
发送字节数,不包括 HTTP 标头,如果没有发送任何字节 |
%B | 发送的字节数,不包括 HTTP 标头 |
%H | 远程主机名 |
%H | 请求协议 |
%l |
来自 |
%m | 请求方法 |
%p | 本地端口 |
%q |
查询字符串(不包括 |
%R | 请求的第一行 |
%s | 响应的 HTTP 状态代码 |
%t | 日期和时间,通用日志格式 |
%u | 已验证的远程用户 |
%U | 请求的 URL 路径 |
%v | 本地服务器名称 |
%D | 处理请求的时间(以毫秒为单位) |
%T | 处理请求的时间(以秒为单位) |
%I | 当前 Request thread name (稍后可以与堆栈追踪进行比较) |
Common |
|
组合 |
|
您还可以从 Cookie、传入标头和响应标头或会话写入信息。语法在 Apache 语法后建模:
-
用于传入标头的
%{I,xxx}
-
%{O,xxx}
用于传出响应标头 -
特定 Cookie 的
%{c,xxx}
-
%{R,xxx}
,其中xxx
是ServletRequest
中的属性 -
%{s,xxx}
,其中xxx
是HttpSession
中的属性
此日志提供了其他配置选项。如需更多信息,请参阅附录中的"access-log 属性"。
15.4.1.2. 控制台访问日志记录
控制台访问日志记录根据 JSON 数据将数据写入 stdout 结构化。
每个访问日志记录都是一行数据。您可以通过日志聚合系统捕获此数据以进行处理。
要配置控制台访问日志记录,请将 console-access-log 设置添加到您要捕获访问日志数据的主机。以下 CLI 命令演示了默认 JBoss EAP 服务器中的默认主机上的配置:
/subsystem=undertow/server=default-server/host=default-host/setting=console-access-log:add
默认情况下,控制台访问日志记录包括以下数据:
日志数据字段名称 | 描述 |
---|---|
eventSource | 请求中的事件源 |
hostName | 处理请求的 JBoss EAP 主机 |
bytesSent | 对请求发送的 JBoss EAP 服务器的字节数 |
dateTime | JBoss EAP 服务器处理请求的日期和时间 |
remoteHost | 请求源自的计算机的 IP 地址 |
remoteUser | 与远程请求关联的用户名 |
requestLine | 已提交的请求 |
responseCode | JBoss EAP 服务器返回的 HTTP 响应代码 |
默认属性始终包含在日志输出中。您可以使用 attributes
属性更改默认日志数据的标签,在某些情况下可以更改数据配置。您还可以使用 attributes
属性在输出中添加额外的日志数据。
日志数据字段名称 | 描述 | 格式 |
---|---|---|
authentication-type | 用于验证与请求关联的用户的身份验证类型。默认标签: authenticationType 使用 key 选项更改此属性的标签。 | authentication-type{} authentication-type={key="authType"} |
bytes-sent | 请求返回的字节数,不包括 HTTP 标头。默认标签: bytesSent 使用 key 选项更改此属性的标签。 | bytes-sent={} bytes-sent={key="sent-bytes"} |
date-time | 接收和处理请求的日期和时间。默认 label: dateTime 使用 key 选项更改此属性的标签。使用 date-format 定义用于格式化 date-time 记录的模式。模式必须是 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'HH: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 参数的名称中。 | path-parameter{names={store,section}} path-parameter{names={store,section}, key-prefix="my-"} |
predicate | predicate 上下文的名称。name 属性是一个以逗号分隔的名称列表,用于解析交换值。使用 key-prefix 属性使密钥是唯一的。如果指定了 key-prefix,前缀会添加到输出中每个 path 参数的名称中。 | predicate{names={store,section}} predicate{names={store,section}, key-prefix="my-"} |
query-parameter | 请求中包含的一个或多个查询参数。name 属性是一个以逗号分隔的名称列表,用于解析交换值。使用 key-prefix 属性使密钥是唯一的。如果指定了 key-prefix,前缀会添加到输出中每个 path 参数的名称中。 | query-parameter{names={store,section}} query-parameter{names={store,section}, key-prefix="my-"} |
query-string | 请求的查询字符串。默认 label: queryString 使用 key 选项更改此属性的标签。使用 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 使用 key 选项更改此属性的标签。使用 obfuscated 属性来模糊处理输出日志记录中的 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-"} |
请求标头 | 请求行。默认标签: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 方案。默认标签: requestScheme 使用 key 选项更改此属性的标签。 | request-scheme{} request-scheme{key=”RequestScheme”} |
request-url | 原始请求 URI。如果由客户端指定,包括主机名、协议等。默认 label: requestUrl 使用 key 选项更改此属性的标签。 | request-url{} request-url{key="RequestURL"} |
resolved-path | 解析的路径。默认 Label: resolvedPath 使用 key 选项更改此属性的标签。 | resolved-path{} resolved-path{key=”ResolvedPath”} |
response-code | 响应代码。默认标签: 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 | 响应代码的文本原因。默认标签: responseReasonPhrase 使用 key 选项更改此属性的标签。 | response-reason-phrase{} response-reason-phrase{key=”ResponseReasonPhrase”} |
response-time | 处理请求的时间。默认 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 |
存储的请求响应。默认标签: storedResponse 使用 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}})