Spring cloud Gateway版本升级踩坑总结

目录

背景:

问题及方案

1 Kubernetes-pom文件中的依赖包名称不同

2 项目引入 OpenFeign 或者 RestTemplate 启动假死

解决方案有以下三种:

1、使用异步方法并且延迟注入 OpenFeignClient (推荐)

2、使用 webclient 代替 Feign

3、关闭基于权重的负载平衡

3 升级之后,feign调用报错

4 熔断机制的核心类库发生变化

5 Not running inside kubernetes. Skipping 'kubernetes' profile activation.


背景:

旧版本:

Spring boot:2.1.8

Spring cloud:Greenwich.SR3

JDK:1.8

新版本:

Spring boot:2.6.8

Spring cloud:2021.0.3

JDK:1.8

问题及方案

1 Kubernetes-pom文件中的依赖包名称不同

这个问题有点坑,当时我问了一下度娘,也没有找到答案,最后上官网查看了一下,才发现问题,所以,以后遇到问题,应该先去官方文档看看,可以解决百分之九十九的问题

文档地址:Spring Cloud Kubernetes | 中文文档

低版本的名称是:


	org.springframework.cloud
	spring-cloud-starter-kubernetes-config

高版本的名称是:


	org.springframework.cloud
	spring-cloud-starter-kubernetes-fabric8-config

2 项目引入 OpenFeign 或者 RestTemplate 启动假死

项目升级之后,启动出现以下情况

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.8)

[2023-02-09 09:46:23.470] [main] [INFO] [org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration]  - Located property source: [BootstrapPropertySource {name='bootstrapProperties-configmap.demo-configmap.test'}]
[2023-02-09 09:46:23.508] [main] [INFO] [org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration]  - Located property source: [BootstrapPropertySource {name='bootstrapProperties-secrets.demo-secret.test'}]
[2023-02-09 09:46:23.569] [main] [WARN] [org.springframework.cloud.kubernetes.commons.profile.AbstractKubernetesProfileEnvironmentPostProcessor]  - Not running inside kubernetes. Skipping 'kubernetes' profile activation.
[2023-02-09 09:46:23.573] [main] [INFO] [cn.test.gateway.Application]  - No active profile set, falling back to 1 default profile: "default"
[2023-02-09 09:46:24.365] [main] [INFO] [org.springframework.cloud.context.scope.GenericScope]  - BeanFactory id=240c07a9-2d7f-39d9-8549-b9fae3417bf0
[2023-02-09 09:46:24.443] [main] [INFO] [org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker]  - Bean 'org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2023-02-09 09:46:24.444] [main] [INFO] [org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker]  - Bean 'org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration$ReactorDeferringLoadBalancerFilterConfig' of type [org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration$ReactorDeferringLoadBalancerFilterConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2023-02-09 09:46:24.445] [main] [INFO] [org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker]  - Bean 'reactorDeferringLoadBalancerExchangeFilterFunction' of type [org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[2023-02-09 09:46:25.623] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [After]
[2023-02-09 09:46:25.623] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Before]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Between]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Cookie]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Header]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Host]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Method]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Path]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Query]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [ReadBody]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [RemoteAddr]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [XForwardedRemoteAddr]
[2023-02-09 09:46:25.624] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [Weight]
[2023-02-09 09:46:25.625] [main] [INFO] [org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator]  - Loaded RoutePredicateFactory [CloudFoundryRouteService]
[2023-02-09 09:46:28.548] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Could not find a port named 'https' or 'http' for service 'cn-demo-v5-wsserver'.
[2023-02-09 09:46:28.549] [boundedElastic-9] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Could not find a port named 'https' or 'http' for service 'istiod'.
[2023-02-09 09:46:28.567] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured.
[2023-02-09 09:46:28.566] [boundedElastic-9] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured.
[2023-02-09 09:46:28.569] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Alternatively name the primary port 'https' or 'http'
[2023-02-09 09:46:28.573] [boundedElastic-9] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Alternatively name the primary port 'https' or 'http'
[2023-02-09 09:46:28.574] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - An incorrect configuration may result in non-deterministic behaviour.
[2023-02-09 09:46:28.574] [boundedElastic-9] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - An incorrect configuration may result in non-deterministic behaviour.
[2023-02-09 09:46:28.577] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Could not find a port named 'https' or 'http' for service 'cn-test-v5-wsserver'.
[2023-02-09 09:46:28.577] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured.
[2023-02-09 09:46:28.577] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Alternatively name the primary port 'https' or 'http'
[2023-02-09 09:46:28.577] [boundedElastic-12] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - An incorrect configuration may result in non-deterministic behaviour.
[2023-02-09 09:46:28.789] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Could not find a port named 'https' or 'http' for service 'kube-dns'.
[2023-02-09 09:46:28.789] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured.
[2023-02-09 09:46:28.790] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Alternatively name the primary port 'https' or 'http'
[2023-02-09 09:46:28.790] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - An incorrect configuration may result in non-deterministic behaviour.
[2023-02-09 09:46:28.790] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Could not find a port named 'https' or 'http' for service 'kube-dns'.
[2023-02-09 09:46:28.790] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured.
[2023-02-09 09:46:28.790] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Alternatively name the primary port 'https' or 'http'
[2023-02-09 09:46:28.790] [boundedElastic-13] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - An incorrect configuration may result in non-deterministic behaviour.
[2023-02-09 09:46:28.828] [boundedElastic-4] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Could not find a port named 'https' or 'http' for service 'selenium-hub'.
[2023-02-09 09:46:28.828] [boundedElastic-4] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Make sure that either the primary-port-name label has been added to the service, or that spring.cloud.kubernetes.discovery.primary-port-name has been configured.
[2023-02-09 09:46:28.828] [boundedElastic-4] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - Alternatively name the primary port 'https' or 'http'
[2023-02-09 09:46:28.828] [boundedElastic-4] [WARN] [org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient]  - An incorrect configuration may result in non-deterministic behaviour.

不要着急,我自有解决方案,不过先分析一下原因:

        是因为启动的时候有死锁导致的。 初始化Bean的时候,主线程执行到DefaultSingletonBeanRegistry.getSingleton方法,会持有一个锁。 然后项目里用了openfeign,在openfeign初始化的时候,会发布一个RefreshRoutesEvent事件,刚好被WeightCalculatorWebFilter捕获到了,执行了routeLocator.ifAvailable(locator -> locator.getRoutes().blockLast());这句代码,blockLast的时候,主线程就挂起了,锁没释放。 然后有其他线程执行到DefaultSingletonBeanRegistry.getSingleton方法的时候(比如上面的locator.getRoutes,实际是异步执行的,线程会调用到DefaultSingletonBeanRegistry.getSingleton方法), 就死锁启不起来了

解决方案有以下三种:

1、使用异步方法并且延迟注入 OpenFeignClient (推荐)

注意点如下:

  1. 注入 OpenFeignClient 必须使用 @Lazy
  2. FeignClent 必须要异步调用,不能同步调用,不然会报不能在xxx线程执行的错
  3. 使用 @EnableFeignClients ,开启 OpenFeign 功能
  4. 使用 @EnableAsync 开启异步执行功能,不然加了 @Async 注解也没用。或者自定义 ExecutorService 进行异步处理。

核心代码实例:

注意点如下
注入 OpenFeignClient 必须使用 @Lazy
FeignClent 必须要异步调用,不能同步调用,不然会报不能在xxx线程执行的错
使用 @EnableFeignClients ,开启 OpenFeign 功能
使用 @EnableAsync 开启异步执行功能,不然加了 @Async 注解也没用。或者自定义 ExecutorService 进行异步处理。
#

2、使用 webclient 代替 Feign

示例代码如下:

//第一步 注入webclident   
  @Bean
  @LoadBalanced     // 如果不添加,无法通过服务名进行调用,只能通过ip调用
  public WebClient.Builder webBuilder(){
      return WebClient.builder();
  }

//第二步 在gateway当中注入
  @Autowired
  WebClient.Builder webBuilder;

//第三步 具体调用方式    这里的“lb”也可以换成http
   Mono toMono = webBuilder.baseUrl("lb://服务名/").build().get().uri(uriBuilder ->
                uriBuilder.path("/api/oauth/check_token").queryParam("参数名称", "参数值").build()
        ).header(HttpHeaders.AUTHORIZATION, token).exchangeToMono(clientResponse -> clientResponse.bodyToMono(Object.class));
 // 不调用subscribe或者block是不会调用服务的
        Object block = toMono.subscribe();
 
   
  

3、关闭基于权重的负载平衡

spring.cloud.gateway.predicate.weight.enabled设置为true时,将为网关中定义的路由,启用基于权重的负载平衡。设置为false时,将禁用基于权重的负载平衡,并且流量将平均分配给服务的所有实例。

3 升级之后,feign调用报错

报错信息如下

[2023-02-10 17:50:10.481] [reactor-http-nio-3] [INFO] [cn.test.gateway.filters.Filter]  - token:4ac15ea7193ba0f1922883dfabc4d48e
[2023-02-10 17:50:12.003] [reactor-http-nio-3] [ERROR] [org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler]  - [8f4cbb3e-1]  500 Server Error for HTTP GET "/v1_admin/goods/battery/admin/info"
feign.RetryableException: Unexpected end of file from server executing GET http://test-admin:8081/test/get?sign=9923dfc364eef935b02b3d55b1324bae&sign_type=MD5×tamp=1676022610
    at feign.FeignException.errorExecuting(FeignException.java:268) ~[feign-core-11.8.jar:?]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ HTTP GET "/v1_admin/goods/battery/admin/info" [ExceptionHandlingWebHandler]
Original Stack Trace:
        at feign.FeignException.errorExecuting(FeignException.java:268) ~[feign-core-11.8.jar:?]
        at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:129) ~[feign-core-11.8.jar:?]
        at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89) ~[feign-core-11.8.jar:?]
        at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-11.8.jar:?]
        at com.sun.proxy.$Proxy137.getManagedAuthAndAppByToken(Unknown Source) ~[?:?]

原因:Spring cloud高版本启动时无法自动加载消息解释器

解决方法:

@Configuration
public class HttpMessageConvertersConfig {

    @Bean
    @ConditionalOnMissingBean
    public HttpMessageConverters messageConverters(ObjectProvider> converters) {
        return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
    }
}

4 熔断机制的核心类库发生变化

在spring-cloud-openfeign2.2.10版本时已经有CircuitBreakers替换掉hystrix的趋势,在3.1.3已经完全被替换掉

文档参考:Spring Cloud OpenFeign

5 Not running inside kubernetes. Skipping 'kubernetes' profile activation.

源码:

void addKubernetesProfile(ConfigurableEnvironment environment) {
  Pod current = utils.currentPod().get();
  if (current != null) {
    if (!hasKubernetesProfile(environment)) {
      environment.addActiveProfile(KUBERNETES_PROFILE);
    }
  }
  if (utils.isInsideKubernetes()) {
    if (hasKubernetesProfile(environment)) {
      LOGGER.debug("'kubernetes' already in list of active profiles");
    } else {
      LOGGER.debug("Adding 'kubernetes' to list of active profiles");
      environment.addActiveProfile(KUBERNETES_PROFILE);
    }
  } else {
    if (LOGGER.isDebugEnabled()) {
      LOGGER.warn("Not running inside kubernetes. Skipping 'kuberntes' profile activation.");
    }
  }
}

设置环境变量,项目启动的时候,会从环境变量中获取Kubernetes相关配置

希望以上信息对大家有所帮助!!!

你可能感兴趣的:(spring,cloud,spring,boot,spring)