17.4. 配置服务器
服务器代表 Undertow 的实例,由多个元素组成:
- 主机
- http-listener
- https-listener
- ajp-listener
主机元素提供虚拟主机配置,而三个侦听器则将该类型的连接提供给 Undertow 实例。
服务器的默认行为是在服务器启动时对请求进行队列。您可以使用主机上的 queue-requests-on-start
属性来更改默认行为。如果此属性设为 true
(默认值),则服务器启动时到达的请求将被保留,直到服务器就绪为止。如果此属性设为 false
,则在服务器完全启动前到达的请求将通过默认响应代码被拒绝。
无论属性值是什么,在服务器完全启动前请求处理不会启动。
您可以使用管理控制台配置 queue-requests-on-start
属性,方法是导航到 Configuration
可以配置多个服务器,从而完全隔离部署和服务器。这在某些情况下很有用,比如多租户环境。
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 配置服务器。您还可以通过导航到 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 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 属性后重新加载服务器。
pattern | 描述 |
---|---|
%a | 远程 IP 地址 |
%A | 本地 IP 地址 |
%b |
发送字节,除 HTTP 标头或 |
%B | 发送的字节数,HTTP 标头除外 |
%h | 远程主机名 |
%H | 请求协议 |
%l |
远程逻辑用户名 from |
%m | 请求方法 |
%p | 本地端口 |
%q |
查询字符串(除 |
%r | 请求的第一行 |
%s | 响应的 HTTP 状态代码 |
%t | 日期和时间,采用通用日志格式格式 |
%u | 经过身份验证的远程用户 |
%U | 请求的 URL 路径 |
%v | 本地服务器名称 |
%D | 处理请求所需的时间,以毫秒为单位 |
%T | 处理请求的时间(以秒为单位) |
%I | 当前 Request 线程名称(稍后与堆栈追踪进行比较) |
common |
|
combined |
|
您还可以从 Cookie、传入的标头和响应标头或会话中写入信息。该语法采用 Apache 语法建模:
-
用于传入标头的
%{I,xx}
-
用于传出响应标头的
%{O,xxx}
-
特定 Cookie
%{C,xxx}
-
%{R,xxx}
wherexxx
是ServletRequest
中的属性 -
%{s,xxx}
wherexxx
是HttpSession
中的属性
此日志提供了其他配置选项。如需更多信息,请参阅附录中的"访问日志属性"。
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
默认情况下,控制台访问日志记录包括以下数据:
日志数据字段名称 | 描述 |
---|---|
eventSource | 请求中事件的源 |
hostName | 处理请求的 JBoss EAP 主机 |
bytesSent | JBoss EAP 服务器响应请求而发送的字节数 |
dateTime | JBoss EAP 服务器处理请求的日期和时间 |
remoteHost | 请求源自的机器的 IP 地址 |
remoteUser | 与远程请求关联的用户名 |
requestLine | 已提交请求 |
responseCode | JBoss EAP 服务器返回的 HTTP 响应代码 |
日志输出中始终包含默认属性。您可以使用 properties 属性
来更改默认日志数据的标签,在某些情况下,也可更改数据配置。您还可以使用 properties 属性
向输出中添加额外的日志数据。
日志数据字段名称 | 描述 | 格式 |
---|---|---|
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}}