成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Cloud Config Server遷移節點或容器化帶來的問題

開發 開發工具
如果您跟我一樣,目前正在使用Spring Cloud Config做為配置中心的話,本篇將來要描述的問題,強烈推薦了解和關注!因為這個問題目前存在于所有的版本中,還沒有完全修復。

 如果您跟我一樣,目前正在使用Spring Cloud Config做為配置中心的話,本篇將來要描述的問題,強烈推薦了解和關注!因為這個問題目前存在于所有的版本中,還沒有完全修復。

[[229497]]

問題現象

為了說明下面的內容,我們可以先嘗試重現一下問題:在一個測試環境中,將Spring Cloud Config的配置中心遷移到另外一個節點上,即配置中心的IP地址發生了變化。在完成遷移之后,我們會發現該環境下各個微服務應用的健康狀態會變得時好時壞,并且在日志中會出現類似下面的報錯:

  1. 2018-05-13 17:01:28,569 WARN  [http-nio-9920-exec-1] org.springframework.cloud.config.client.ConfigServerHealthIndicator - Health check failed 
  2. java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing 
  3.     at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:132) 
  4.     at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator$$FastClassBySpringCGLIB$$fa44b2a.invoke(<generated>) 
  5.     at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 
  6.     at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) 
  7.     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
  8.     at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:91) 
  9.     at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:287) 
  10.     at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:164) 
  11.     at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:118) 
  12.     at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:153) 
  13.     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
  14.     at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) 
  15.     at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator$$EnhancerBySpringCGLIB$$3a43a1f4.locate(<generated>) 
  16.     at org.springframework.cloud.config.client.ConfigServerHealthIndicator.getPropertySource(ConfigServerHealthIndicator.java:54) 
  17.     at org.springframework.cloud.config.client.ConfigServerHealthIndicator.doHealthCheck(ConfigServerHealthIndicator.java:35) 
  18.     at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:43) 
  19.     at org.springframework.boot.actuate.health.CompositeHealthIndicator.health(CompositeHealthIndicator.java:68) 
  20.     at org.springframework.boot.actuate.endpoint.HealthEndpoint.invoke(HealthEndpoint.java:85) 
  21.     at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.getCurrentHealth(HealthMvcEndpoint.java:177) 
  22.     at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.getHealth(HealthMvcEndpoint.java:166) 
  23.     at org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(HealthMvcEndpoint.java:143) 
  24.     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
  25.     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
  26.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
  27.     at java.lang.reflect.Method.invoke(Method.java:498) 
  28.     at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) 
  29.     at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) 
  30.     at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) 
  31.     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 
  32.     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 
  33.     at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
  34.     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) 
  35.     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) 
  36.     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
  37.     at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
  38.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) 
  39.     at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
  40.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
  41.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 
  42.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  43.     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
  44.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  45.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  46.     at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) 
  47.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  48.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  49.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  50.     at com.yonghui.feign.filter.RequestOriginFilter.doFilter(RequestOriginFilter.java:41) 
  51.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  52.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  53.     at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) 
  54.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  55.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  56.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  57.     at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
  58.     at com.yonghui.rpc.feature.web.boot.RpcHolder4BootFilter.doFilterInternal(RpcHolder4BootFilter.java:29) 
  59.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  60.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  61.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  62.     at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
  63.     at com.yonghui.rpc.feature.web.boot.FeatureSupport4BootFilter.doFilterInternal(FeatureSupport4BootFilter.java:24) 
  64.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  65.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  66.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  67.     at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) 
  68.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  69.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  70.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  71.     at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) 
  72.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  73.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  74.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  75.     at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
  76.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  77.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  78.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  79.     at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) 
  80.     at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
  81.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
  82.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
  83.     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) 
  84.     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
  85.     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) 
  86.     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
  87.     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) 
  88.     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
  89.     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 
  90.     at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) 
  91.     at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
  92.     at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) 
  93.     at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) 
  94.     at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
  95.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 
  96.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 
  97.     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
  98.     at java.lang.Thread.run(Thread.java:748) 
  99. Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://192.168.5.103:9010/config-server/test"Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused) 
  100.     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:674) 
  101.     at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:621) 
  102.     at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:539) 
  103.     at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.getRemoteEnvironment(ConfigServicePropertySourceLocator.java:172) 
  104.     at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:93) 
  105.     ... 95 more 
  106. Caused by: java.net.ConnectException: Connection refused (Connection refused) 
  107.     at java.net.PlainSocketImpl.socketConnect(Native Method) 
  108.     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) 
  109.     at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) 
  110.     at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) 
  111.     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) 
  112.     at java.net.Socket.connect(Socket.java:589) 
  113.     at java.net.Socket.connect(Socket.java:538) 
  114.     at sun.net.NetworkClient.doConnect(NetworkClient.java:180) 
  115.     at sun.net.www.http.HttpClient.openServer(HttpClient.java:463) 
  116.     at sun.net.www.http.HttpClient.openServer(HttpClient.java:558) 
  117.     at sun.net.www.http.HttpClient.<init>(HttpClient.java:242) 
  118.     at sun.net.www.http.HttpClient.New(HttpClient.java:339) 
  119.     at sun.net.www.http.HttpClient.New(HttpClient.java:357) 
  120.     at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1220) 
  121.     at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1156) 
  122.     at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1050) 
  123.     at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:984) 
  124.     at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:78) 
  125.     at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) 
  126.     at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) 
  127.     at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:660) 
  128.     ... 99 more 

可以看到類似上面的健康檢查失敗錯誤,但是并不是一直這樣,這個環境下的微服務會出現時好時壞的情況,那么為什么會出現這種現象呢?

原因分析

從錯誤日志中我們可以發現一個非常關鍵的信息:I/O error on GET request for "http://192.168.5.103:9010/config-server/test"。

報錯說明了微服務檢查配置中心獲取配置的連接是否暢通的時候出現了連接不上的情況,但是這個鏈接信息其實并不是當前配置中心的地址,而是我們遷移之前的配置中心的地址。

從健康檢查的實現源碼ConfigServerHealthIndicator中為入口去分析和調試,我們可以解答上面現象的兩個疑問:

  1.  @Override 
  2.    protected void doHealthCheck(Builder builder) throws Exception { 
  3.     PropertySource<?> propertySource = getPropertySource(); 
  4.     builder.up(); 
  5.     if (propertySource instanceof CompositePropertySource) { 
  6.         List<String> sources = new ArrayList<>(); 
  7.         for (PropertySource<?> ps : ((CompositePropertySource) propertySource).getPropertySources()) { 
  8.             sources.add(ps.getName()); 
  9.         } 
  10.         builder.withDetail("propertySources", sources); 
  11.     } else if (propertySource!=null) { 
  12.         builder.withDetail("propertySources", propertySource.toString()); 
  13.     } else { 
  14.         builder.unknown().withDetail("error""no property sources located"); 
  15.     } 
  16.    } 
  17.  
  18. private PropertySource<?> getPropertySource() { 
  19.     long accessTime = System.currentTimeMillis(); 
  20.     if (isCacheStale(accessTime)) { 
  21.         this.lastAccess = accessTime; 
  22.         this.cached = locator.locate(this.environment); 
  23.     } 
  24.     return this.cached; 

為什么會健康檢查訪問的還是老的配置中心地址?

真正導致健康檢查失敗的語句是getPropertySource中的 this.cached = locator.locate(this.environment);而這里的具體實現在org.springframework.cloud.config.client.ConfigServicePropertySourceLocator類中,具體實現如下:

  1. @Override 
  2. @Retryable(interceptor = "configServerRetryInterceptor"
  3. public org.springframework.core.env.PropertySource<?> locate( 
  4.             org.springframework.core.env.Environment environment) { 
  5.     ConfigClientProperties properties = this.defaultProperties.override(environment); 
  6.     CompositePropertySource composite = new CompositePropertySource("configService"); 
  7.     RestTemplate restTemplate = this.restTemplate == null ? getSecureRestTemplate(properties) 
  8.                 : this.restTemplate; 
  9.     Exception error = null
  10.     String errorBody = null
  11.     logger.info("Fetching config from server at: " + properties.getRawUri()); 
  12.         ... 

可以看到,真正去訪問的地址是直接從properties.getRawUri()獲取的,它已經是一個固化的值,而不是通過服務發現機制來動態獲取的。這就導致了當我們把配置中心做了遷移,或者直接部署在容器中出現重啟的時候,IP發生變化,而所有的微服務還以為訪問的是原來的配置中心地址,就會出現健康檢查失敗的問題,導致服務不可用的現象。

為什么健康檢查時好時壞?

上面的問題會導致健康檢查失敗,但是這個服務并不是一直都不好,而是間斷性的出現不健康。這主要還是健康檢查時間中的機制導致,這里可以具體看ConfigServerHealthIndicator的getPropertySource函數,該方法執行的時候中間并不是每一次檢查都會去訪問配置中心(執行locator.locate(this.environment)方法),因此客戶端的健康檢查并不會每次都健康檢查失敗,從而出現了微服務健康檢查時好時壞的情況。

如何解決

該問題目前也在官方的issue中被提出,還處于open狀態,具體可見:https://github.com/spring-cloud/spring-cloud-config/issues/514

由于該問題目前并沒有得到解決,雖然提交了一個PR,但是還有待完善以及提供一些測試,原本想完全處理好之后再寫一篇文章,但是發現最近不少問過類似問題,所以索性先寫一篇文章,提醒一下用戶以及給一些相關的建議。

當前版本上不太容易通過擴展的方式去解決的這個問題,所以大家可以變通的去避免這個問題:

  • 部署在虛擬機上而不是容器上,避免IP的變動
  • 可以考慮關閉微服務隊config客戶端的健康檢查,增加參數management.health.config.enabled=false;但是這個操作有一個弊端,雖然遷移不會引發服務時好時壞的問題了,但是如果有動態配置刷新需求,如果遷移了配置中心,刷新配置操作也是會失敗的。

【本文為51CTO專欄作者“翟永超”的原創稿件,轉載請通過51CTO聯系作者獲取授權】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2018-07-27 15:43:24

Spring Clou管理架構

2023-01-13 16:22:54

云遷移云計算

2017-10-31 14:58:11

Spring Clou配置信息問題

2018-06-22 15:46:45

Spring Clou加密處理

2023-09-12 13:12:23

服務器系統

2021-10-10 00:03:38

NodePodTerminating

2017-08-25 10:03:16

無服務器Google

2012-07-10 10:08:52

2012-03-16 10:44:14

密碼

2021-08-18 10:36:43

Sping社區實驗項目服務器

2025-05-29 05:59:56

2009-06-18 13:44:05

Spring2.0spring2.5

2013-09-13 17:32:30

華為BYODBYOD華為

2018-07-10 14:55:32

Git存儲配置

2013-01-31 10:16:16

2023-07-06 16:36:45

云遷移云計算

2018-06-20 14:45:14

兼容性云計算虛擬機

2012-11-01 10:56:50

BYOD虛擬化

2011-11-16 10:58:55

虛擬化虛擬機云計算

2009-05-11 19:17:40

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 超碰97人人人人人蜜桃 | 亚洲成人在线视频播放 | 秋霞性生活| 午夜丰满少妇一级毛片 | 欧美日韩在线观看视频 | 亚洲91| 免费在线视频一区二区 | 一区二区视频 | 麻豆亚洲 | 欧美精品一区二区三区四区五区 | 日日摸日日添日日躁av | 成人黄色a| 视频三区| 久久国产视频一区 | 亚洲经典一区 | 精品国产欧美一区二区 | 精品国产不卡一区二区三区 | 激情五月激情综合网 | 亚洲一区在线播放 | 人妖av| 成人视屏在线观看 | 国产三级一区二区三区 | 人人艹人人爽 | 欧美一级网站 | 免费黄色的视频 | 欧美精品乱码99久久影院 | 少妇性l交大片免费一 | 成人久久18免费网站图片 | 久草在线 | 久久精品亚洲 | 免费av观看 | 免费观看成人av | 欧美日韩视频 | 三级成人片 | 不卡一区 | 日本三级电影免费观看 | 日韩精品一区二区三区在线观看 | 在线精品观看 | 久久精品久久久久久 | 国产一区二区三区在线免费观看 | 国产欧美精品区一区二区三区 |