系统A/B F5探测问题分析报告

问题描述:

2020年11月、2021年1月,系统A和系统B在使用我行自有开发框架升级投产时,发生F5探测失效问题。表现为应用启动正常,手动测试服务可用,但F5探测机制失效,无法判定应用是否存活。两个应用均选择了回退。

当前我行F5探测机制有两种方式,一种是根据端口号判定应用是否存活,另一种是配置某一具体服务,通过服务的返回来确定应用是否存活。考虑到端口探活其实并不准确,时常发生应用启动失败但端口仍被占用的情况,因此网络推荐采用具体服务的探测方式。经调研,系统A和系统B均采用配置服务方式完成F5探测。

端口探测在传输层完成,传输的内容理论上都是byte[],因此从理论上并不会出现应用正常但探测不到的情况。所以重点分析配置服务完成探测的场景。

问题分析:

系统A和系统B在升级前,均采用Weblogic+WAR包形式部署。升级后采用JAR包部署,使用类似于SpringBoot的嵌入式Tomcat启动。考虑到服务探测只判定对HTTP的返回头进行判定,因此排查的重点就锁定在了Tomcat与Weblogic的差异上。

使用Linux自带的Telnet,输入如下命令

 telent ip port
 GET /serviceName HTTP/1.0
 HOST ip 

此时Weblogic返回样式:

 HTTP/1.1 200 OK
 Server: Apache-Coyote/1.1
 Content-Type: text/xml
 Date: Sun, 07 Feb 2021 11:54:07 GMT
 Connection: close 

使用同样的命令探测自有开发框架应用,返回样式:

 HTTP/1.1 200
 Content-Type: text/xml
 Date: Sun, 07 Feb 2021 11:50:11 GMT
 Connection: close 

由此可见一个明显的差别,即探测自有开发框架应用的返回结果,HTTP头返回“HTTP/1.1 200”,而探测Weblogic的返回结果,HTTP头返回“HTTP/1.1 200 OK”。核对F5配置的探测返回结果判定,为“200 OK”。且此处判定是通过全字符串匹配方式,则可以解释为何应用启动成功,但未有探测结果。尝试将F5配置的探测返回结果判定改为“200”,此时探测生效。故可以明确该问题为自有开发框架与Weblogic的报文头返回结果差异。

由于自有开发框架采用了嵌入式的Tomcat,故猜想是否是因为Web容器内置导致的这个问题。因此继续对外置的Tomcat进行telnet测试。自有开发框架内置的Tomcat版本为8.0.50,故选择同样版本的外置Tomcat进行测试,返回结果仍为“HTTP/1.1 200”。至此可明确,该问题为Weblogic与Tomcat的返回头差异所致。

但生产上之前也存在诸多使用Tomcat部署应用,为何没有其他应用提出过这个差异问题?排除一部分应用采用端口探测,理论上仍然存在着既使用了Tomcat,又使用服务探测的应用。故继续对Tomcat进行的调研。考虑到生产上存在着大量的Tomcat 6和Tomcat 7,故对Tomcat 6/7也进行了telnet测试,均返回“HTTP/1.1 200 OK”。至此可明确,该问题是由于Tomcat 8版本引发。

 HTTP/1.1 200 OK
 Content-Type: text/xml
 Date: Sun, 07 Feb 2021 12:01:11 GMT
 Connection: close 

至此,问题便转化为为何Tomcat在版本升级后,将HTTP返回头进行了修改。查阅Tomcat版本发行记录未获得答案,因此选择查阅了HTTP协议的协议文本对于状态码的解释。HTTP 1.0和HTTP 1.1版本对于状态码的解释均在第六章,且差异不大。故此处只摘录HTTP 1.1的定义:

The Status-Code element is a 3-digit integer result code of the attempt to understand and satisfy the request. These codes are fully defined in Section 10. The Reason-Phrase is intended to give a short textual description of the Status-Code. The Status-Code is intended for use by automata and the Reason-Phrase is intended for the human user. The client is not required to examine or display the Reason-Phrase.

The first digit of the Status-Code defines the class of response. The last two digits do not have any categorization role. There are 5 values for the first digit:
 • 1xx: Informational - Request received, continuing process
 • 2xx: Success - The action was successfully received, understood, and accepted
 • 3xx: Redirection - Further action must be taken in order to complete the request
 • 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
 • 5xx: Server Error - The server failed to fulfill an apparently valid request

The individual values of the numeric status codes defined for HTTP/1.1, and an example set of corresponding Reason-Phrase's, are presented below. The reason phrases listed here are only recommendations -- they MAY be replaced by local equivalents without affecting the protocol. 

由协议文本易知,200被称作状态码,OK被称为结果短语。注意,协议明确指出了“The client is not required to examine or display the Reason-Phrase”,即客户端不被强制返回结果短语字段。因此Tomcat选择不返回OK本身符合HTTP协议规范要求。且协议也明确了“The reason phrases listed here are only recommendations — they may be replaced by local equivalents without affecting the protocol”,即结果短语在这里列出只是被推荐的,他们有可能被本地化的实现替代。因此,“OK”本身并不属于HTTP协议规范的内容。理论上如果有一个中文化的Web服务器,返回“200 成功”也是符合HTTP协议规范的实现。故以“200 OK”作为HTTP返回头,实际上并不完全符合HTTP协议。因此推知,Tomcat 8修正了之前这一不严谨的返回头处理方式,仅返回状态码即“200”。

继续通过查询资料可知,Tomcat 8在server.xml配置文件<Connector>标签中添加sendReasonPhrase=”true”即可。但在Tomcat 9中将这种过渡性方案也予以取消,由此可见HTTP协议对此处的定义方式。

解决方案:

建议所有采用F5服务探测的应用,将返回结果判定由“200 OK”全字符串匹配,修改为“200”,或仅匹配返回码即可。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注