前言
前段时间,因项目被扫出大量漏洞,全是因为依赖版本过低,存在高中危漏洞需要升级。正好本来也有规划集群升级,因为工作量大迟迟落实不了,正好有这次修漏洞的机会,升级微服务集群。这篇文章主要记录了本人的升级记录,遇到的问题解决方法,仅供参考。
项目背景
项目微服务技术栈: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中加入依赖,过期的配置会提示:
<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以后不允许循环依赖
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、跨域头修改
由原来的修改为
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配置过期
The use of configuration keys that have been renamed was found in the environment:Property source 'ApolloBootstrapPropertySources':Key: spring.datasource.dataReplacement: spring.sql.init.data-locationsKey: spring.datasource.platformReplacement: spring.sql.init.platformKey: spring.datasource.schemaReplacement: spring.sql.init.schema-locations
修改:
sql:init:platform: mysql#执行的sql语句data-locations: classpath:data.sql#执行的建表语句schema-locations: classpath:schema.sql
11、Eureka 配置的修改
instance-id: ${spring.cloud.client.ip-address}:${server.port}metadata-map:user-name: ${spring.security.user.name}user-password: ${spring.security.user.password}
12、上传配置的修改
spring:servlet:#最大上传大小,MBmultipart:max-file-size: 1000MBmax-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
@Bean
public LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {return new BlockingLoadBalancerClient(loadBalancerClientFactory);
}
14、调用接口报NoSuchMethodError: org.springframework.boot.web.servlet.error.ErrorController.getErrorPath
增加如下类
@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.*/@Beanpublic 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;@Overridepublic int accept(Method method) {if (METHOD.equals(method.getName())) {return 0;}return 1;}}private enum LookupHandlerMethodInterceptor implements MethodInterceptor {INSTANCE;@Overridepublic 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// NoSuchMethodErrorreturn 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);}@Overridepublic 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 lookupHandlerenhancer.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、负责均衡找不到下游服务的问题
增加如下类:
public class RibbonEurekaClientConfig {@Autowiredprivate DiscoveryClient discoveryClient;@Bean@Lazypublic IPing ribbonPing() {return new DummyPing();}@Bean@Lazypublic IRule ribbonRule(IClientConfig clientConfig) {AvailabilityFilteringRule rule = new AvailabilityFilteringRule();rule.initWithNiwsConfig(clientConfig);return rule;}@Bean@Lazypublic ServerList<?> ribbonServerList(IClientConfig clientConfig) {return new ServerList<Server>() {@Overridepublic List<Server> getInitialListOfServers() {return new ArrayList<>();}@Overridepublic 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 系列文章
- Spring Boot 源码阅读初始化环境搭建
- Spring Boot 框架整体启动流程详解
- Spring Boot 系统初始化器详解
- Spring Boot 监听器详解
- Spring Boot banner详解
- Spring Boot 属性配置解析
- Spring Boot 属性加载原理解析
- Spring Boot 异常报告器解析
- Spring Boot 3.x 自动配置详解