问题现象:
某产品使用CSE的隔离功能,并且配置了errorThresholdPercentage=15%。 在一次用户突发请求的过程中,由于一个服务(B)产生大量的超时,调用B的服务A触发了实例隔离。后来用户恢复了被隔离的服务B,但是服务A调用B仍然没有恢复,所有实例经过3个小时后,还是没有恢复。
问题日志:
2019-02-04 21:58:12.641 [jgw-getgameauthsign-executor-50] INFO The Service AppGalleryJointOperationUserService's instance b8fe6f79288411e9b7f100163e0b130d has been isolated for a while, give a single test opportunity. - at org.apache.servicecomb.loadbalance.filter.IsolationDiscoveryFilter.allowVisit(IsolationDiscoveryFilter.java:123)
2019-02-04 21:58:12.643 [jgw-getgameauthsign-executor-50] ERROR Invoke all server failed. Operation CONSUMER AppGalleryJointOperationUserService.usage-auth.signAuth, e=com.netflix.client.ClientException: Load balancer does not have available server for client: default - at org.apache.servicecomb.loadbalance.LoadbalanceHandler$3.onExecutionFailed(LoadbalanceHandler.java:321)
问题分析:
从第一条日志看,尝试使用这个实例访问,但紧接着的打印找不到实例。开始分析的时候,被这个错误引导,以为是代码bug导致的,不过经过大量分析代码,没发现bug。 后来发现产品在一次业务逻辑执行过程中,会调用同一个服务的x和y两个方法。第一条日志是调用x方法的时候打印的,第二条日志是调用y方法的时候打印的,因此确定了x方法是调用成功的,而调用y方法的时候没成功。所以问题根因为一个实例被隔离后,虽然尝试使用这个实例,但是错误率长期大于15%,导致实例没恢复, 所以实例持续处于隔离状态。
这种情况通常发生于突发情况导致的隔离,比如每次突发用户请求导致总请求数为100000, 错误70000,错误率为70%,如果需要降到15%,那么需要尝试55000次。但是隔离后,尝试是非常缓慢的,每个single test周期才尝试一次,需要要尝试这么多次,就需要非常长的时间。
建议:
在配置隔离策略的时候,建议业务不要使用errorThresholdPercentage(默认没开启),防止突发情况导致恢复缓慢。缺省情况采用的是连续错误次数来隔离,一旦一个实例访问成功,马上恢复实例的访问。 这样可以起到快速隔离,快速恢复的效果,通常是我们预期的效果。