SpringCloud 微服务集群升级记录(1.5.x-2.7.18)

2023-12-02 10:41:32 浏览数 (1)

前言

前段时间,因项目被扫出大量漏洞,全是因为依赖版本过低,存在高中危漏洞需要升级。正好本来也有规划集群升级,因为工作量大迟迟落实不了,正好有这次修漏洞的机会,升级微服务集群。这篇文章主要记录了本人的升级记录,遇到的问题解决方法,仅供参考。

项目背景

项目微服务技术栈:Spring Boot 1.5.x 、Spring Cloud、Kafka、RabbitMq、Mysql、Eureka、Apollo、Nacos。Spring Boot 是1.5.x 版本非常老旧,Spring Cloud 版本也早就停更。根据Nacos的兼容情况,Spring Boot 的版本为2.6.13,但目前最新版是2.7.18,由于3.x跟2.x区别较大,因此决定使用2.7.18试试,Spring Cloud 版本为2021.0.5.0。

升级记录

在xml中加入依赖,过期的配置会提示:

代码语言:javascript复制
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-properties-migrator</artifactId>
   <scope>runtime</scope>
</dependency>

1、Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class is com.mysql.cj.jdbc.Driver’

  • 需要更新Mysql驱动

2、Caused by: java.lang.IllegalStateException: Could not resolve element type of Iterable type @。。。。。web.bind.annotation.RequestParam java.util.List. Not declared?

  • @RequestParam(value = "Long[]") List projectIds 此类的代码不能再使用

3、spring.rabbitmq.publisher-confirms 过期

4、Canonical names should be kebab-case (‘-’ separated)

  • 不能使用驼峰形式,用- 隔开

5、import org.springframework.cloud.netflix.feign 修改为 import org.springframework.cloud.openfeign

6、2.6以后不允许循环依赖

代码语言:javascript复制
spring:
   main:
     # Spring Boot 2.6以后 默认不允许循环依赖
   allow-circular-references: true
   	#允许bean覆盖
   	allow-bean-definition-overriding: true

7、spring.cloud.client.ipAddress 都修改为 spring.cloud.client.ip-address

8、跨域头修改

由原来的修改为

代码语言:javascript复制
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOriginPattern("*");

9、gateway 升级要注意去掉重复跨域头

spring.cloud.gateway.default-filters[0] = DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST

10、database配置过期

代码语言:javascript复制
The use of configuration keys that have been renamed was found in the environment:

Property source 'ApolloBootstrapPropertySources':
	Key: spring.datasource.data
		Replacement: spring.sql.init.data-locations
	Key: spring.datasource.platform
		Replacement: spring.sql.init.platform
	Key: spring.datasource.schema
		Replacement: spring.sql.init.schema-locations

修改:

代码语言:javascript复制
  sql:
    init:
      platform: mysql
      #执行的sql语句
      data-locations: classpath:data.sql
      #执行的建表语句
      schema-locations: classpath:schema.sql

11、Eureka 配置的修改

代码语言:javascript复制
instance-id: ${spring.cloud.client.ip-address}:${server.port}

metadata-map:
  user-name: ${spring.security.user.name}
  user-password: ${spring.security.user.password}

12、上传配置的修改

代码语言:javascript复制
spring:
  servlet:
  #最大上传大小,MB
    multipart:
      max-file-size: 1000MB
      max-request-size: 1000MB

13、原有zuul适配

org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose(Ljava/lang/String;Lorg/springframework/cloud/client/loadbalancer/Request;)Lorg/springframework/cloud/client/ServiceInstance

增加如下Bean

代码语言:javascript复制
@Bean
public LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
   return new BlockingLoadBalancerClient(loadBalancerClientFactory);
}

14、调用接口报NoSuchMethodError: org.springframework.boot.web.servlet.error.ErrorController.getErrorPath

增加如下类

代码语言:javascript复制
@Configuration
public class ZuulConfiguration {
    /**
     * The path returned by ErrorController.getErrorPath() with Spring Boot < 2.5
     * (and no longer available on Spring Boot >= 2.5).
     */
    private static final String ERROR_PATH = "/error";
    private static final String METHOD = "lookupHandler";

    /**
     * Constructs a new bean post-processor for Zuul.
     *
     * @param routeLocator    the route locator.
     * @param zuulController  the Zuul controller.
     * @param errorController the error controller.
     * @return the new bean post-processor.
     */
    @Bean
    public ZuulPostProcessor zuulPostProcessor(@Autowired RouteLocator routeLocator,
                                               @Autowired ZuulController zuulController,
                                               @Autowired(required = false) ErrorController errorController) {
        return new ZuulPostProcessor(routeLocator, zuulController, errorController);
    }

    private enum LookupHandlerCallbackFilter implements CallbackFilter {
        INSTANCE;

        @Override
        public int accept(Method method) {
            if (METHOD.equals(method.getName())) {
                return 0;
            }
            return 1;
        }
    }

    private enum LookupHandlerMethodInterceptor implements MethodInterceptor {
        INSTANCE;

        @Override
        public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            if (ERROR_PATH.equals(args[0])) {
                // by entering this branch we avoid the ZuulHandlerMapping.lookupHandler method to trigger the
                // NoSuchMethodError
                return null;
            }
            return methodProxy.invokeSuper(target, args);
        }
    }

    private static final class ZuulPostProcessor implements BeanPostProcessor {

        private final RouteLocator routeLocator;
        private final ZuulController zuulController;
        private final boolean hasErrorController;

        ZuulPostProcessor(RouteLocator routeLocator, ZuulController zuulController, ErrorController errorController) {
            this.routeLocator = routeLocator;
            this.zuulController = zuulController;
            this.hasErrorController = (errorController != null);
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (hasErrorController && (bean instanceof ZuulHandlerMapping)) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(ZuulHandlerMapping.class);
                enhancer.setCallbackFilter(LookupHandlerCallbackFilter.INSTANCE); // only for lookupHandler
                enhancer.setCallbacks(new Callback[] {LookupHandlerMethodInterceptor.INSTANCE, NoOp.INSTANCE});
                Constructor<?> ctor = ZuulHandlerMapping.class.getConstructors()[0];
                return enhancer.create(ctor.getParameterTypes(), new Object[] {routeLocator, zuulController});
            }
            return bean;
        }
    }
}

15、负责均衡找不到下游服务的问题

增加如下类:

代码语言:javascript复制
public class RibbonEurekaClientConfig {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Bean
    @Lazy
    public IPing ribbonPing() {
        return new DummyPing();
    }

    @Bean
    @Lazy
    public IRule ribbonRule(IClientConfig clientConfig) {
        AvailabilityFilteringRule rule = new AvailabilityFilteringRule();
        rule.initWithNiwsConfig(clientConfig);
        return rule;
    }

    @Bean
    @Lazy
    public ServerList<?> ribbonServerList(IClientConfig clientConfig) {

        return new ServerList<Server>() {
            @Override
            public List<Server> getInitialListOfServers() {
                return new ArrayList<>();
            }

            @Override
            public List<Server> getUpdatedListOfServers() {
                List<Server> serverList = new ArrayList<>();
                List<ServiceInstance> instances = discoveryClient.getInstances(clientConfig.getClientName());
                if (instances != null && instances.size() == 0) {
                    return serverList;
                }
                for (ServiceInstance instance : instances) {
                    if (instance.isSecure()) {
                        serverList.add(new Server("https", instance.getHost(), instance.getPort()));
                    } else {
                        serverList.add(new Server("http", instance.getHost(), instance.getPort()));
                    }
                }
                return serverList;
            }
        };
    }

}

在Spring Boot 启动类上配置

@RibbonClients(defaultConfiguration = RibbonEurekaClientConfig.class)

基于Spring Boot 3.1.0 系列文章

  1. Spring Boot 源码阅读初始化环境搭建
  2. Spring Boot 框架整体启动流程详解
  3. Spring Boot 系统初始化器详解
  4. Spring Boot 监听器详解
  5. Spring Boot banner详解
  6. Spring Boot 属性配置解析
  7. Spring Boot 属性加载原理解析
  8. Spring Boot 异常报告器解析
  9. Spring Boot 3.x 自动配置详解

0 人点赞