自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring Cloud Config Server遷移節(jié)點(diǎn)或容器化帶來(lái)的問(wèn)題

開(kāi)發(fā) 開(kāi)發(fā)工具
如果您跟我一樣,目前正在使用Spring Cloud Config做為配置中心的話,本篇將來(lái)要描述的問(wèn)題,強(qiáng)烈推薦了解和關(guān)注!因?yàn)檫@個(gè)問(wèn)題目前存在于所有的版本中,還沒(méi)有完全修復(fù)。

 如果您跟我一樣,目前正在使用Spring Cloud Config做為配置中心的話,本篇將來(lái)要描述的問(wèn)題,強(qiáng)烈推薦了解和關(guān)注!因?yàn)檫@個(gè)問(wèn)題目前存在于所有的版本中,還沒(méi)有完全修復(fù)。

[[229497]]

問(wèn)題現(xiàn)象

為了說(shuō)明下面的內(nèi)容,我們可以先嘗試重現(xiàn)一下問(wèn)題:在一個(gè)測(cè)試環(huán)境中,將Spring Cloud Config的配置中心遷移到另外一個(gè)節(jié)點(diǎn)上,即配置中心的IP地址發(fā)生了變化。在完成遷移之后,我們會(huì)發(fā)現(xiàn)該環(huán)境下各個(gè)微服務(wù)應(yīng)用的健康狀態(tài)會(huì)變得時(shí)好時(shí)壞,并且在日志中會(huì)出現(xiàn)類似下面的報(bào)錯(cuò):

  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 

可以看到類似上面的健康檢查失敗錯(cuò)誤,但是并不是一直這樣,這個(gè)環(huán)境下的微服務(wù)會(huì)出現(xiàn)時(shí)好時(shí)壞的情況,那么為什么會(huì)出現(xiàn)這種現(xiàn)象呢?

原因分析

從錯(cuò)誤日志中我們可以發(fā)現(xiàn)一個(gè)非常關(guān)鍵的信息:I/O error on GET request for "http://192.168.5.103:9010/config-server/test"。

報(bào)錯(cuò)說(shuō)明了微服務(wù)檢查配置中心獲取配置的連接是否暢通的時(shí)候出現(xiàn)了連接不上的情況,但是這個(gè)鏈接信息其實(shí)并不是當(dāng)前配置中心的地址,而是我們遷移之前的配置中心的地址。

從健康檢查的實(shí)現(xiàn)源碼ConfigServerHealthIndicator中為入口去分析和調(diào)試,我們可以解答上面現(xiàn)象的兩個(gè)疑問(wèn):

  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; 

為什么會(huì)健康檢查訪問(wèn)的還是老的配置中心地址?

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

  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.         ... 

可以看到,真正去訪問(wèn)的地址是直接從properties.getRawUri()獲取的,它已經(jīng)是一個(gè)固化的值,而不是通過(guò)服務(wù)發(fā)現(xiàn)機(jī)制來(lái)動(dòng)態(tài)獲取的。這就導(dǎo)致了當(dāng)我們把配置中心做了遷移,或者直接部署在容器中出現(xiàn)重啟的時(shí)候,IP發(fā)生變化,而所有的微服務(wù)還以為訪問(wèn)的是原來(lái)的配置中心地址,就會(huì)出現(xiàn)健康檢查失敗的問(wèn)題,導(dǎo)致服務(wù)不可用的現(xiàn)象。

為什么健康檢查時(shí)好時(shí)壞?

上面的問(wèn)題會(huì)導(dǎo)致健康檢查失敗,但是這個(gè)服務(wù)并不是一直都不好,而是間斷性的出現(xiàn)不健康。這主要還是健康檢查時(shí)間中的機(jī)制導(dǎo)致,這里可以具體看ConfigServerHealthIndicator的getPropertySource函數(shù),該方法執(zhí)行的時(shí)候中間并不是每一次檢查都會(huì)去訪問(wèn)配置中心(執(zhí)行l(wèi)ocator.locate(this.environment)方法),因此客戶端的健康檢查并不會(huì)每次都健康檢查失敗,從而出現(xiàn)了微服務(wù)健康檢查時(shí)好時(shí)壞的情況。

如何解決

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

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

當(dāng)前版本上不太容易通過(guò)擴(kuò)展的方式去解決的這個(gè)問(wèn)題,所以大家可以變通的去避免這個(gè)問(wèn)題:

  • 部署在虛擬機(jī)上而不是容器上,避免IP的變動(dòng)
  • 可以考慮關(guān)閉微服務(wù)隊(duì)config客戶端的健康檢查,增加參數(shù)management.health.config.enabled=false;但是這個(gè)操作有一個(gè)弊端,雖然遷移不會(huì)引發(fā)服務(wù)時(shí)好時(shí)壞的問(wèn)題了,但是如果有動(dòng)態(tài)配置刷新需求,如果遷移了配置中心,刷新配置操作也是會(huì)失敗的。

【本文為51CTO專欄作者“翟永超”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)51CTO聯(lián)系作者獲取授權(quán)】

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

責(zé)任編輯:武曉燕 來(lái)源: 51CTO專欄
相關(guān)推薦

2018-07-27 15:43:24

Spring Clou管理架構(gòu)

2017-10-31 14:58:11

Spring Clou配置信息問(wèn)題

2023-01-13 16:22:54

云遷移云計(jì)算

2018-06-22 15:46:45

Spring Clou加密處理

2023-09-12 13:12:23

服務(wù)器系統(tǒng)

2021-10-10 00:03:38

NodePodTerminating

2017-08-25 10:03:16

無(wú)服務(wù)器Google

2021-08-18 10:36:43

Sping社區(qū)實(shí)驗(yàn)項(xiàng)目服務(wù)器

2012-07-10 10:08:52

2009-06-18 13:44:05

Spring2.0spring2.5

2018-07-10 14:55:32

Git存儲(chǔ)配置

2012-03-16 10:44:14

密碼

2013-09-13 17:32:30

華為BYODBYOD華為

2013-01-31 10:16:16

2018-06-20 14:45:14

兼容性云計(jì)算虛擬機(jī)

2023-07-06 16:36:45

云遷移云計(jì)算

2021-11-16 11:45:00

SpringSpring ClouJava

2018-08-30 15:48:43

ConsulSpring Clou開(kāi)源

2011-11-16 10:58:55

虛擬化虛擬機(jī)云計(jì)算

2023-11-28 08:36:16

Spring中Body讀取
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)