错误的意思是:已达到可容忍的服务器重连接错误的最大数目。
有两个解决思路:一个将这个值设置的更大;然后是排查自己连接服务哪儿出了问题。
先说在哪儿设置这个值:在拉取nacos服务的注解配置中,添加一个属性maxRetry,这个值源码中默认给的是3,可以将其设置的更大一些。
1 @Configuration 2 @EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848", namespace = "xxxxxxxxxxxxxxxxxx", maxRetry = "10")) 3 @NacosPropertySources({ 4 5 @NacosPropertySource(dataId = "url.properties", groupId = "test_group", autoRefreshed = true), 6 7 8 @NacosPropertySource(dataId = "db.properties", groupId = "test_group", autoRefreshed = true), 9 10 @NacosPropertySource(dataId = "xxl-job.properties", groupId = "test_group", autoRefreshed = true) 11 }) 12 public class NacosConfiguration { 13 14 }
nacos-clinent架包中,找到ServerHttpAgent类。
包的全路经:com.alibaba.nacos.client.config.http.ServerHttpAgent
可以看到设置错误的最大连接数目默认值为3,private int maxRetry = 3;
在方法httpGet中,如果出现异常或者没有提前返回,则判断serverListMgr.getIterator().hasNext(),如果为true则使用serverListMgr.getIterator().next()更新currentServerAddr,为false则递减maxRetry,maxRetry=0时则抛出异常[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached
1 /* 2 * Copyright 1999-2018 Alibaba Group Holding Ltd. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.alibaba.nacos.client.config.http; 17 18 import com.alibaba.nacos.api.PropertyKeyConst; 19 import com.alibaba.nacos.api.common.Constants; 20 import com.alibaba.nacos.api.exception.NacosException; 21 import com.alibaba.nacos.client.config.impl.HttpSimpleClient; 22 import com.alibaba.nacos.client.config.impl.HttpSimpleClient.HttpResult; 23 import com.alibaba.nacos.client.config.impl.ServerListManager; 24 import com.alibaba.nacos.client.config.impl.SpasAdapter; 25 import com.alibaba.nacos.client.config.utils.IOUtils; 26 import com.alibaba.nacos.client.identify.STSConfig; 27 import com.alibaba.nacos.client.utils.TemplateUtils; 28 import com.alibaba.nacos.client.utils.JSONUtils; 29 import com.alibaba.nacos.client.utils.LogUtils; 30 import com.alibaba.nacos.client.utils.ParamUtil; 31 import com.alibaba.nacos.client.utils.StringUtils; 32 import com.fasterxml.jackson.annotation.JsonProperty; 33 import com.fasterxml.jackson.core.type.TypeReference; 34 import org.apache.commons.lang3.math.NumberUtils; 35 import org.slf4j.Logger; 36 import java.io.IOException; 37 import java.net.ConnectException; 38 import java.net.HttpURLConnection; 39 import java.net.SocketTimeoutException; 40 import java.net.URL; 41 import java.util.ArrayList; 42 import java.util.Date; 43 import java.util.List; 44 import java.util.Properties; 45 import java.util.concurrent.Callable; 46 47 /** 48 * Server Agent 49 * 50 * @author water.lyl 51 */ 52 public class ServerHttpAgent implements HttpAgent { 53 54 private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class); 55 56 /** 57 * @param path 相对于web应用根,以/开头 58 * @param headers 59 * @param paramValues 60 * @param encoding 61 * @param readTimeoutMs 62 * @return 63 * @throws IOException 64 */ 65 @Override 66 public HttpResult httpGet(String path, Listheaders, List paramValues, String encoding, 67 long readTimeoutMs) throws IOException { 68 final long endTime = System.currentTimeMillis() + readTimeoutMs; 69 final boolean isSSL = false; 70 71 String currentServerAddr = serverListMgr.getCurrentServerAddr(); 72 int maxRetry = this.maxRetry; 73 74 do { 75 try { 76 List newHeaders = getSpasHeaders(paramValues); 77 if (headers != null) { 78 newHeaders.addAll(headers); 79 } 80 HttpResult result = HttpSimpleClient.httpGet( 81 getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, 82 readTimeoutMs, isSSL); 83 if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR 84 || result.code == HttpURLConnection.HTTP_BAD_GATEWAY 85 || result.code == HttpURLConnection.HTTP_UNAVAILABLE) { 86 LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", 87 serverListMgr.getCurrentServerAddr(), result.code); 88 } else { 89 // Update the currently available server addr 90 serverListMgr.updateCurrentServerAddr(currentServerAddr); 91 return result; 92 } 93 } catch (ConnectException ce) { 94 LOGGER.error("[NACOS ConnectException httpGet] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), ce.getMessage()); 95 } catch (SocketTimeoutException stoe) { 96 LOGGER.error("[NACOS SocketTimeoutException httpGet] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), stoe.getMessage()); 97 } catch (IOException ioe) { 98 LOGGER.error("[NACOS IOException httpGet] currentServerAddr: " + serverListMgr.getCurrentServerAddr(), ioe); 99 throw ioe; 100 } 101 102 if (serverListMgr.getIterator().hasNext()) { 103 currentServerAddr = serverListMgr.getIterator().next(); 104 } else { 105 maxRetry --; 106 if (maxRetry < 0) { 107 throw new ConnectException("[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached"); 108 } 109 serverListMgr.refreshCurrentServerAddr(); 110 } 111 112 } while (System.currentTimeMillis() <= endTime); 113 114 LOGGER.error("no available server"); 115 throw new ConnectException("no available server"); 116 } 117 118 @Override 119 public HttpResult httpPost(String path, List headers, List paramValues, String encoding, 120 long readTimeoutMs) throws IOException { 121 final long endTime = System.currentTimeMillis() + readTimeoutMs; 122 boolean isSSL = false; 123 124 String currentServerAddr = serverListMgr.getCurrentServerAddr(); 125 int maxRetry = this.maxRetry; 126 127 do { 128 129 try { 130 List newHeaders = getSpasHeaders(paramValues); 131 if (headers != null) { 132 newHeaders.addAll(headers); 133 } 134 135 HttpResult result = HttpSimpleClient.httpPost( 136 getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, 137 readTimeoutMs, isSSL); 138 if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR 139 || result.code == HttpURLConnection.HTTP_BAD_GATEWAY 140 || result.code == HttpURLConnection.HTTP_UNAVAILABLE) { 141 LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", 142 currentServerAddr, result.code); 143 } else { 144 // Update the currently available server addr 145 serverListMgr.updateCurrentServerAddr(currentServerAddr); 146 return result; 147 } 148 } catch (ConnectException ce) { 149 LOGGER.error("[NACOS ConnectException httpPost] currentServerAddr: {}, err : {}", currentServerAddr, ce.getMessage()); 150 } catch (SocketTimeoutException stoe) { 151 LOGGER.error("[NACOS SocketTimeoutException httpPost] currentServerAddr: {}, err : {}", currentServerAddr, stoe.getMessage()); 152 } catch (IOException ioe) { 153 LOGGER.error("[NACOS IOException httpPost] currentServerAddr: " + currentServerAddr, ioe); 154 throw ioe; 155 } 156 157 if (serverListMgr.getIterator().hasNext()) { 158 currentServerAddr = serverListMgr.getIterator().next(); 159 } else { 160 maxRetry --; 161 if (maxRetry < 0) { 162 throw new ConnectException("[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached"); 163 } 164 serverListMgr.refreshCurrentServerAddr(); 165 } 166 167 } while (System.currentTimeMillis() <= endTime); 168 169 LOGGER.error("no available server, currentServerAddr : {}", currentServerAddr); 170 throw new ConnectException("no available server, currentServerAddr : " + currentServerAddr); 171 } 172 173 @Override 174 public HttpResult httpDelete(String path, List headers, List paramValues, String encoding, 175 long readTimeoutMs) throws IOException { 176 final long endTime = System.currentTimeMillis() + readTimeoutMs; 177 boolean isSSL = false; 178 179 String currentServerAddr = serverListMgr.getCurrentServerAddr(); 180 int maxRetry = this.maxRetry; 181 182 do { 183 try { 184 List newHeaders = getSpasHeaders(paramValues); 185 if (headers != null) { 186 newHeaders.addAll(headers); 187 } 188 HttpResult result = HttpSimpleClient.httpDelete( 189 getUrl(currentServerAddr, path), newHeaders, paramValues, encoding, 190 readTimeoutMs, isSSL); 191 if (result.code == HttpURLConnection.HTTP_INTERNAL_ERROR 192 || result.code == HttpURLConnection.HTTP_BAD_GATEWAY 193 || result.code == HttpURLConnection.HTTP_UNAVAILABLE) { 194 LOGGER.error("[NACOS ConnectException] currentServerAddr: {}, httpCode: {}", 195 serverListMgr.getCurrentServerAddr(), result.code); 196 } else { 197 // Update the currently available server addr 198 serverListMgr.updateCurrentServerAddr(currentServerAddr); 199 return result; 200 } 201 } catch (ConnectException ce) { 202 LOGGER.error("[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), ce.getMessage()); 203 } catch (SocketTimeoutException stoe) { 204 LOGGER.error("[NACOS SocketTimeoutException httpDelete] currentServerAddr:{}, err : {}", serverListMgr.getCurrentServerAddr(), stoe.getMessage()); 205 } catch (IOException ioe) { 206 LOGGER.error("[NACOS IOException httpDelete] currentServerAddr: " + serverListMgr.getCurrentServerAddr(), ioe); 207 throw ioe; 208 } 209 210 if (serverListMgr.getIterator().hasNext()) { 211 currentServerAddr = serverListMgr.getIterator().next(); 212 } else { 213 maxRetry --; 214 if (maxRetry < 0) { 215 throw new ConnectException("[NACOS HTTP-DELETE] The maximum number of tolerable server reconnection errors has been reached"); 216 } 217 serverListMgr.refreshCurrentServerAddr(); 218 } 219 220 } while (System.currentTimeMillis() <= endTime); 221 222 LOGGER.error("no available server"); 223 throw new ConnectException("no available server"); 224 } 225 226 private String getUrl(String serverAddr, String relativePath) { 227 return serverAddr + "/" + serverListMgr.getContentPath() + relativePath; 228 } 229 230 public static String getAppname() { 231 return ParamUtil.getAppName(); 232 } 233 234 public ServerHttpAgent(ServerListManager mgr) { 235 serverListMgr = mgr; 236 } 237 238 public ServerHttpAgent(ServerListManager mgr, Properties properties) { 239 serverListMgr = mgr; 240 init(properties); 241 } 242 243 public ServerHttpAgent(Properties properties) throws NacosException { 244 serverListMgr = new ServerListManager(properties); 245 init(properties); 246 } 247 248 private void init(Properties properties) { 249 initEncode(properties); 250 initAkSk(properties); 251 initMaxRetry(properties); 252 } 253 254 private void initEncode(Properties properties) { 255 encode = TemplateUtils.stringEmptyAndThenExecute(properties.getProperty(PropertyKeyConst.ENCODE), new Callable () { 256 @Override 257 public String call() throws Exception { 258 return Constants.ENCODE; 259 } 260 }); 261 } 262 263 private void initAkSk(Properties properties) { 264 String ramRoleName = properties.getProperty(PropertyKeyConst.RAM_ROLE_NAME); 265 if (!StringUtils.isBlank(ramRoleName)) { 266 STSConfig.getInstance().setRamRoleName(ramRoleName); 267 } 268 269 String ak = properties.getProperty(PropertyKeyConst.ACCESS_KEY); 270 if (StringUtils.isBlank(ak)) { 271 accessKey = SpasAdapter.getAk(); 272 } else { 273 accessKey = ak; 274 } 275 276 String sk = properties.getProperty(PropertyKeyConst.SECRET_KEY); 277 if (StringUtils.isBlank(sk)) { 278 secretKey = SpasAdapter.getSk(); 279 } else { 280 secretKey = sk; 281 } 282 } 283 284 private void initMaxRetry(Properties properties) { 285 maxRetry = NumberUtils.toInt(String.valueOf(properties.get(PropertyKeyConst.MAX_RETRY)), Constants.MAX_RETRY); 286 } 287 288 @Override 289 public synchronized void start() throws NacosException { 290 serverListMgr.start(); 291 } 292 293 private List getSpasHeaders(List paramValues) throws IOException { 294 List newHeaders = new ArrayList (); 295 // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权 296 if (STSConfig.getInstance().isSTSOn()) { 297 STSCredential sTSCredential = getSTSCredential(); 298 accessKey = sTSCredential.accessKeyId; 299 secretKey = sTSCredential.accessKeySecret; 300 newHeaders.add("Spas-SecurityToken"); 301 newHeaders.add(sTSCredential.securityToken); 302 } 303 304 if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotEmpty(secretKey)) { 305 newHeaders.add("Spas-AccessKey"); 306 newHeaders.add(accessKey); 307 List signHeaders = SpasAdapter.getSignHeaders(paramValues, secretKey); 308 if (signHeaders != null) { 309 newHeaders.addAll(signHeaders); 310 } 311 } 312 return newHeaders; 313 } 314 315 private STSCredential getSTSCredential() throws IOException { 316 boolean cacheSecurityCredentials = STSConfig.getInstance().isCacheSecurityCredentials(); 317 if (cacheSecurityCredentials && sTSCredential != null) { 318 long currentTime = System.currentTimeMillis(); 319 long expirationTime = sTSCredential.expiration.getTime(); 320 int timeToRefreshInMillisecond = STSConfig.getInstance().getTimeToRefreshInMillisecond(); 321 if (expirationTime - currentTime > timeToRefreshInMillisecond) { 322 return sTSCredential; 323 } 324 } 325 String stsResponse = getSTSResponse(); 326 STSCredential stsCredentialTmp = JSONUtils.deserializeObject(stsResponse, 327 new TypeReference () { 328 }); 329 sTSCredential = stsCredentialTmp; 330 LOGGER.info("[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}", sTSCredential.getCode(), 331 sTSCredential.getAccessKeyId(), sTSCredential.getLastUpdated(), sTSCredential.getExpiration()); 332 return sTSCredential; 333 } 334 335 private static String getSTSResponse() throws IOException { 336 String securityCredentials = STSConfig.getInstance().getSecurityCredentials(); 337 if (securityCredentials != null) { 338 return securityCredentials; 339 } 340 String securityCredentialsUrl = STSConfig.getInstance().getSecurityCredentialsUrl(); 341 HttpURLConnection conn = null; 342 int respCode; 343 String response; 344 try { 345 conn = (HttpURLConnection) new URL(securityCredentialsUrl).openConnection(); 346 conn.setRequestMethod("GET"); 347 conn.setConnectTimeout(ParamUtil.getConnectTimeout() > 100 ? ParamUtil.getConnectTimeout() : 100); 348 conn.setReadTimeout(1000); 349 conn.connect(); 350 respCode = conn.getResponseCode(); 351 if (HttpURLConnection.HTTP_OK == respCode) { 352 response = IOUtils.toString(conn.getInputStream(), Constants.ENCODE); 353 } else { 354 response = IOUtils.toString(conn.getErrorStream(), Constants.ENCODE); 355 } 356 } catch (IOException e) { 357 LOGGER.error("can not get security credentials", e); 358 throw e; 359 } finally { 360 if (null != conn) { 361 conn.disconnect(); 362 } 363 } 364 if (HttpURLConnection.HTTP_OK == respCode) { 365 return response; 366 } 367 LOGGER.error("can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}", 368 securityCredentialsUrl, respCode, response); 369 throw new IOException( 370 "can not get security credentials, responseCode: " + respCode + ", response: " + response); 371 } 372 373 @Override 374 public String getName() { 375 return serverListMgr.getName(); 376 } 377 378 @Override 379 public String getNamespace() { 380 return serverListMgr.getNamespace(); 381 } 382 383 @Override 384 public String getTenant() { 385 return serverListMgr.getTenant(); 386 } 387 388 @Override 389 public String getEncode() { 390 return encode; 391 } 392 393 @SuppressWarnings("PMD.ClassNamingShouldBeCamelRule") 394 private static class STSCredential { 395 @JsonProperty(value = "AccessKeyId") 396 private String accessKeyId; 397 @JsonProperty(value = "AccessKeySecret") 398 private String accessKeySecret; 399 @JsonProperty(value = "Expiration") 400 private Date expiration; 401 @JsonProperty(value = "SecurityToken") 402 private String securityToken; 403 @JsonProperty(value = "LastUpdated") 404 private Date lastUpdated; 405 @JsonProperty(value = "Code") 406 private String code; 407 408 public String getAccessKeyId() { 409 return accessKeyId; 410 } 411 412 public Date getExpiration() { 413 return expiration; 414 } 415 416 public Date getLastUpdated() { 417 return lastUpdated; 418 } 419 420 public String getCode() { 421 return code; 422 } 423 424 @Override 425 public String toString() { 426 return "STSCredential{" + 427 "accessKeyId='" + accessKeyId + '\'' + 428 ", accessKeySecret='" + accessKeySecret + '\'' + 429 ", expiration=" + expiration + 430 ", securityToken='" + securityToken + '\'' + 431 ", lastUpdated=" + lastUpdated + 432 ", code='" + code + '\'' + 433 '}'; 434 } 435 } 436 437 private String accessKey; 438 private String secretKey; 439 private String encode; 440 private int maxRetry = 3; 441 private volatile STSCredential sTSCredential; 442 final ServerListManager serverListMgr; 443 444 }