I am participating in the 2022 Spring Recruitment series – experience review, click here for more details

Dear students, RECENTLY I have been building a personal website, which involves the service construction of gateway. “SpringCloudGateway explodes vulnerabilities, quickly see your service in the trick?” , so I decided to directly upgrade my gateway service to version 3.1.1, but without upgrading, I don’t know, there are so many pits, here is a record of the pits encountered, I hope you have a reference after encountering.

Project source code address: gitee.com/wei_rong_xi…

Project transformation background: juejin.cn/post/707224…

I. Project Introduction

First of all, LET me show you the overall composition of my current project:

  • The parent projectbsolver
    • The gatewaybsolver-gateway
    • Code generatorbsolver-generator
    • The public relies onbsolver-starter
    • pagebsolver-ui
    • Customer servicebsolver-user

My project version depends on the following:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12. RELEASE</version>
    <relativePath/> <! -- lookup parent from repository -->
</parent>
Copy the code
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.2.7. RELEASE</version>
</dependency>
Copy the code

Ii. Upgrade plan

Based on the overall project architecture, there are currently two upgrade schemes:

  • Plan 1: Upgrade all projects
  • Solution 2: Upgrade the Gateway separately

I chose plan two. Why? Inevitably after trying to meet more pits.

Let’s take a look at how gateway’s internal dependencies have changed since it was upgraded to version 3.1.1:

As shown above, the group has two points:

  • Springcloud is up to 3.1.1
  • The springboot version reaches 2.6.3

This is a far cry from the 2.3.12.release springboot version I used earlier, which is 29 versions apart.

2.1 Solution 1 Upgrade Mode

Let’s start with the upgrade mode of scheme 1. All of my child projects are dependent on the parent project bsolver:

<parent>
    <groupId>com.wjbgn</groupId>
    <artifactId>bsolver</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
</parent>
Copy the code

So we just need to change the bsolver version and use 2.6.3 directly:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.3</version>
    <relativePath/> <! -- lookup parent from repository -->
</parent>
Copy the code

Accordingly, since SpringBoot has been upgraded, the nacOS dependencies we use will also be upgraded. There is a small hole here, and we can see the version in maven repository:

Normally around the above version, the internal dependency should be higher, but in this dependency:

  • 2021.1The corresponding SpringBoot version is2.4.2
  • 2021.0.1.0The corresponding SpringBoot version is2.6.3

I don’t want to go into why, so here’s the obvious choice: 2021.0.1.0:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2021.0.1.0</version>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2021.0.1.0</version>
</dependency>
Copy the code

At this point, I thought I was done, so I started the project and, boy, reported the following exception:

Failed to start the bean 'documentationPluginsBootstrapper; nested exception is java.lang.NullPointerExceptionCopy the code

After some searching, this is the error reported by Swagger2.

Yes, my project uses KNIfe4J as the interface documentation:

After half a day of processing, I still found that it could not be solved, and finally came to the conclusion that Swagger2 did not adapt to the higher version of Springboot at all.

If I wanted to use a lower version of SpringBoot, I would not be able to upgrade 3.1.1 for SpringGateway.

Interface documentation was necessary, so I ended up abandoning option 1 and trying to upgrade only the gateway service.

It is also so, can be said to be a blessing in disguise, because the pit behind it!

2.2 Solution 2 Upgrade Mode

This solution is mainly for the upgrade of gateway service:

  • Benefits: Other services remain versioned and do not affect the use of interface documents.
  • Disadvantages: You need to maintain a set of dependencies, even if they are duplicated with other services can not be shared.

Let’s start the transformation:

  • Modify the parent dependency of the gateway service:
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.3</version>
    <relativePath/> <! -- lookup parent from repository -->
</parent>
Copy the code
  • Gateway version 3.1.1 dependencies were introduced
<! -- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-gateway -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>3.1.1</version>
</dependency>
Copy the code
  • The dependency of NacOS is introduced separately:
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2021.0.1.0</version>
</dependency>

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2021.0.1.0</version>
</dependency>
Copy the code
  • Introduce bootstrapstrap dependencies
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
    <version>3.1.1</version>
</dependency>
Copy the code

Why introduce it separately?

We used to change the configuration file from Properties to YAML format when using SpringCloud, but the upgrade didn’t work because bootstrap.yml was not loaded after Gateway version 2.4.5, which caused our service to start reading the configuration.

  • The introduction ofloadbalancer
<! - fegin component - >
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
   <version>3.1.1</version>
</dependency>
<! -- Feign Client for loadBalancing -->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-loadbalancer</artifactId>
   <version>3.1.1</version>
</dependency>
Copy the code

Why introduce it separately?

I didn’t know I was going to introduce it, but there was a problem. All interfaces accessed through the gateway could not be accessed, and 503 error was reported, even for interface documents.

Spring-cloud-starter-openfeign also needs to be introduced

If your gateway service wants to call other services through the Feign interface normally behind it, just do it.

2.3 Transformation Results

Other services except gateway do not need to be adjusted, we directly start all services to see the result:

  • Service registry for NACOS

  • Gateway access interface documentation

  • The gateway pom. XML

    I have put the entire file here, some of which are designed to depend on JWT etc., and some of the packaged configuration etc., but it is not the focus of this article. If you need to know, you can go to the source repository mentioned in the beginning to download.


      
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/> <! -- lookup parent from repository -->
    </parent>
    <groupId>com.wjbgn</groupId>
    <artifactId>bsolver-gateway</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>bsolver-gateway</name>
    <description>The gateway</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <packaging>jar</packaging>

    <dependencies>

        <! -- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>3.1.1</version>
        </dependency>

        <! Bootstrap. yml is not loaded after upgrade to 2.4.5.
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2021.0.1.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2021.0.1.0</version>
        </dependency>

        <! - fegin component - >
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>3.1.1</version>
        </dependency>
        <! -- Feign Client for loadBalancing -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
            <version>3.1.1</version>
        </dependency>

        <! -- SpringBoot Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <! -- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.9</version>
        </dependency>

        <! -- jwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>


        <! -- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.3.12. RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.11.1</version>
        </dependency>


        <! -- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>

        <! -- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <! -- SpringBoot packages plugins using Maven -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.1</version>
                <configuration>
                    <descriptors>
                        <descriptor>./src/main/resources/package/package.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <! -- Specify the location of the configuration file -->
                <directory>src/main/resources</directory>
                <includes>
                    <! -- Read all files under Resources, include, does not allow it, or excludes file below it -->
                    <include>/ * * *</include>
                </includes>
                <! -- Open the substitution tag, such as our '@env' substitution -->
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

    <! Configure different profiles for different production environments -->
    <profiles>
        <profile>
            <! - development - >
            <id>dev</id>
            <activation>
                <! -- Default development environment -->
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <! -- custom variable name env as the tag, inside the tag is our configuration file environment suffix -->
                <env>dev</env>
            </properties>
        </profile>
        <profile>
            <! - production - >
            <id>pro</id>
            <properties>
                <env>pro</env>
            </properties>
        </profile>
        <profile>
            <! - test - >
            <id>test</id>
            <properties>
                <env>test</env>
            </properties>
        </profile>
    </profiles>


</project>
Copy the code

Third, summary

We encountered many problems and learned a lot about this upgrade. However, the project is still being improved and enriched, and there may be more problems in the future due to this transformation, so we will update it here.

A tip: The technology is changing so much that we still need some time to understand the changes so that we can be comfortable with them when we encounter them.

This transformation is mainly due to the super Power bug of the gateway. Without this bug, I might not have contacted these components of the new version. In general, I have gained a lot.