I am a kite, the public number “ancient kite”, a both depth and breadth of programmers encourage division, a plan to write poetry but write up the code of rural code farmers! Articles will be included in JavaNewBee, and there will be a Java back-end knowledge map, which will cover the path from small white to big cow.

It’s been a month since Spring Boot 2.3 was released, and I just wanted to give it a try. In addition to the regular upgrades, most of the upgrades are targeted at Docker, which makes you believe that Docker containerized microservices are already on the trend. If you haven’t used it yet, it’s too late.

This upgrade mainly includes the following aspects, then follow me to try it.


The preparatory work

To illustrate the new features of Spring Boot 2.3, you must create a project to experiment with.

Create a project and start it

1. Create a Spring Boot project. You can go to https://start.spring.io/ or use the built-in function of IDEA to create a Spring Boot project. Choose version 2.3.1, JDK or dear Java 8, and introduce two dependencies of Web and Actuator.

image-20200623155810851

It is important to note that at the time of writing, Spring Boot 2.3.1 cannot be downloaded from the central repository, and the official Spring Boot milestone repository needs to be added.

<repositories>
  <repository>
    <id>spring-milestone</id>
    <name>Spring Milestone Repository</name>
    <url>https://repo.spring.io/milestone</url>
 </repository> </repositories> Copy the code

2. Introduce the Maven plugin into the POM file

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
 <version>2.3.1. RELEASE</version>  </plugin>  </plugins> </build> Copy the code

3. Add a Controller for testing.

@RestController
public class PlayController {

    @GetMapping(value = "play")
    public String play(a){
 return "hey, play with me!";  } } Copy the code

4. Start the project

mvn spring-boot:run
Copy the code

5, go to http://localhost:8080/play, the success of project startup

image-20200623161822953

Better Docker support

If you don’t want to use Docker, then directly into the jar package, use the following command

mvn package spring-boot:repackage
Copy the code
image-20200623162023503

The Jar package can then be deployed to the server, perhaps using an automated deployment tool rather than a Jenkins or homegrown system.

Docker packaging way before

Leaving aside mature automated deployment processes in companies (especially large ones), I’m talking about small factories in general or individual projects.

If you already use Docker in previous versions, you can write your own Dockerfile, and then write your own scripts to use The Dockerfile image package, or use Maven plugin, such as dockerfile-maven-plugin. I wrote an article about Spring Boot and Docker to implement microservice deployment, which is used in this way, can be compared.

Cloud Native Buildpacks

If you know anything about Dockerfiles, you know how to build an image with Dockerfiles, you create a Dockerfile and you write in it a sequence of actions that you need to do to build an image, Cloud Native Buildpacks, on the other hand, eliminates the need to configure similar process files, making developers’ work much easier and more efficient. This is not the most important, but it provides a higher level of abstraction, makes the layering of the image clearer, and makes efficient use of the layer cache, so that when we make changes to the application, we can build the image again quickly, for example, when we change the application only a few lines of code. So when we build the image with Buildpacks, we only need to rebuild in the application layer and use caching for the other layers, that is, only rebuild for the layers that have changed.

Spring Boot 2.3 Docker mode

First, make sure you have Docker services started locally.

Spring Boot 2.3 is the official Docker Maven plugin, no need to rely on third parties. We already introduced this Maven plug-in when we created the project earlier.

This plug-in not only provides the function of mirroring package, but also other common functions, such as run, repackage, etc.

image-20200623154127475

Cloud Native Buildpacks is the way Spring Boot 2.3 builds Docker image packs.

Let’s make a mirror package and try it out

mvn spring-boot:build-image
Copy the code

You think you’re gonna see results soon? You’re still too young.

What’s wrong with developers in Greater China

For Chinese developers, packaging doesn’t go well, and it’s easy to see why. If there were no accidents, there would be such mistakes. If there were no mistakes, there might be accidents.

[ERROR] Failed to execute goal org. Springframework. The boot: spring - the boot - maven - plugin: 2.3.1. RELEASE: build - image (default - cli)  on project play: Execution default - cli of goal org. Springframework. The boot: spring - the boot - maven - plugin: 2.3.1. RELEASE: build - image failed: Docker API call to 'localhost/v1.24 / images/create? FromImage =gcr. IO % 2fPaketo-buildPacks %2Fbuilder% 3abase-platform-api-0.3 'failed with status code 500 "Internal Server Error" and message "Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" -> [Help 1]Copy the code

The reason for this problem is that Buildpacks calls the Docker API’s method of creating images. Go to https://gcr.io and pull some base images from above, which is Google Cloud, Is Google’s container repository, however for Chinese developers, this address is 404.

So we need to add a system-level proxy, or configure the proxy specifically for Docker. I am the agent configured in Docker. The influence of system agent is too great. My machine is installed is Docker Desktop, directly open the Settings, add agent inside it can (don’t ask me how to do agent, ask me is no agent).

image-20200623174349112

All right, run the command again with the tiger action above

mvn spring-boot:build-image
Copy the code

Depending on your network speed, wait a while and the following result will appear, indicating that the image was created successfully.


You can then view it using the Docker images command. That was 40 years ago.

image-20200623222649235

Start the container with this image

Start the container directly using commands.

Docker run-it p8080:8080 play:0.0.1-SNAPSHOTCopy the code

Then access port 8080 and get the correct result, indicating successful startup.

image-20200623161822953

A feature of the Docker Image is that each layer is an increment of the change of the previous layer. There is a tool called Dive that can clearly see what is contained in the hierarchy. For specific installation and use, please search by yourself.

A tip for Dive to look at, since the mirror layer contains many instructions, we chose to look only at the incremental content relative to the previous layer, using the Ctrl+L key combination.

image-20200622231229994

Then press Tab to enter the view, then Ctrl+U to remove the options that have not changed, that is, to see only the parts that have changed.

image-20200622225041292

The up and down arrows can then be used to switch layers. For example, the figure below shows the changes of an 18 M layer relative to the previous layer. It can be seen that this layer is actually the application layer, containing many classes and third-party dependencies of the current application, etc.

image-20200623223512781

Layered jars

It is convenient to layer and package the configuration. The simplest way is to add the following configuration to the POM file:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <version>2.3.1. RELEASE</version>
  <configuration>
 <layers>  <enabled>true</enabled>  </layers>  </configuration> </plugin> Copy the code

After the layered configuration is added, regular command packaging is still used

mvn package spring-boot:repackage
Copy the code

In fact, hierarchical packaging is no different from the previous packaging method, the typed package is almost the same as before, hierarchical is just a logical abstraction. The structure of the jar package is as follows (jar package is actually a zip package, you can unzip to see the directory structure)

image-20200624073901950

The classpath. Idx and layers.idx files you can see in the boot-INF directory of the JAR package are the key to layering the JAR.

By default, there are four layers.

  • dependenciesVersion-free dependencies that have little impact no matter how your application changes.
  • spring-boot-loaderSpring Boot loads classes.
  • snapshot-dependenciesDependency packages that have requirements on the application version, for example, dependency packages that may need to be upgraded after the application is upgraded.
  • applicationApplications compile classes and configuration files, etc.

You can see this layering in layers.idx, which can be opened with a normal text editor, such as sublime. When you open it, you see a yamL-like structure where the four layers and the directories they refer to are clearly listed.

- "dependencies":
  - "BOOT-INF/lib/"
- "spring-boot-loader":
  - "org/"
- "snapshot-dependencies":
- "application":  - "BOOT-INF/classes/"  - "BOOT-INF/classpath.idx"  - "BOOT-INF/layers.idx"  - "META-INF/" Copy the code

The classpath. Idx file lists the dependent JAR packages and will be loaded in that order.

- "Spring - the boot - starter - physical - 2.3.1. The jar." "
- "Spring - the boot - starter - 2.3.1. The jar." "
- "Spring - the boot - 2.3.1. RELEASE. The jar." "
- "Spring - the boot - autoconfigure - 2.3.1. The jar." "
- "Spring - the boot - starter - logging - 2.3.1. The jar." "
- "Logback - the classic - 1.2.3. Jar" - "Logback - core - 1.2.3. Jar" - "Log4j - to - slf4j - 2.13.3. Jar" Copy the code

Custom hierarchical structure

Spring Boot 2.3 also provides custom layering if we want to add new layers on top of the default 4. The configuration is also simple. The plugin configuration is as follows, specifying layers.xml as a custom layer configuration

<configuration>
  <layers>
    <enabled>true</enabled>
    <configuration>${project.basedir}/src/layers.xml</configuration>
  </layers>
</configuration> Copy the code

The layers.xml configuration looks like this

<layers xmlns="http://www.springframework.org/schema/boot/layers"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
 https://www.springframework.org/schema/boot/layers/layers-2.3.xsd">
 <application>
 <into layer="spring-boot-loader">  <include>org/springframework/boot/loader/**</include>  </into>  <into layer="application" />  </application>  <dependencies>  <into layer="snapshot-dependencies">  <include>*:*:*SNAPSHOT</include>  </into>  <into layer="dependencies" />  </dependencies>  <layerOrder>  <layer>dependencies</layer>  <layer>spring-boot-loader</layer>  <layer>snapshot-dependencies</layer>  <layer>application</layer>  </layerOrder> </layers> Copy the code

When you enable layering, you can use -djarmode to view layering.

Java -djarmode = layerTools -jar target/play-0.0.1 -snapshot.jar listCopy the code

The result is layering, such as by default, with four default layering listed.

dependencies
spring-boot-loader
snapshot-dependencies
application
Copy the code

An aside:

Djarmode is actually a Java-Agent. For java-Agent, you can see the article I wrote earlier, which uses it for Java debugging tools, hot deployment, and JVM monitoring tools.

Meaning of layering packages

Talk about layered packages for a long time, then what is the use of layered packages?

Let’s just say it’s designed to work with Docker. If you don’t use Docker, or use the original JAR package, it doesn’t work. If anything, it makes you more aware of the dependencies of your project.

Layered packages combine with Docker

Buildpacks will help you layer your images, and Spring Boot 2.3 will provide you with jar jars that take the layering of images one step further.

So let’s turn on the layered configuration, and then re-type the Docker image to have a look.

mvn spring-boot:build-image
Copy the code

Then use the Dive tool to see if the Docker image is better layered with the layered JAR feature enabled. The previous layers are the same, they are all integrated images and configurations, and the four layers starting from the 18 MB layer are the four layers with layering enabled. Corresponding to dependencies, spring-boot-loader, snapshot-loader, and Application respectively

image-20200624090924915

Take this 5.4K application layer for example.

image-20200624092311622

Buildpacks will use caching. If this layer stays the same, you don’t need to repackage the layer. So if you only change the content in your application, For example, if you add a Controller or configuration file, you only need to repackage this layer, which is a few K, tens of K will not be very large, so that the packaging speed is very fast, or a hundred-megabyte image package will take a period of time.

Graceful stop function

What is called graceful shutdown? Suppose this is a distributed service, and one of the physical machines of the service needs to be shut down and restarted before shutting down the physical machine.

Ways to turn off services, such as:

  1. I don’t care. I’ll just shut down the machine, and as for service, it’s up to me, not god.
  2. Easy to do, kill -9, one line command to solve, also quite easy.

Well, it is ok, but there are some problems, such as the current service instance is processing requests, you click it to end, who can stand, do not be too exciting.

Let’s change the play method in the previous Controller, add a delay, wait 6 seconds before returning, simulate a slower request.

@GetMapping(value = "play")
public String play(a) throws InterruptedException{
  Thread.sleep(6000);
  return "hey, play with me!";
}
Copy the code

The effect is that you visit the address and wait six seconds before it says hey, play with me! .

If I kill the process within those 6 seconds, the following annoying screen will appear in the browser.

image-20200624095526291

Enable graceful shutdown

You only need to add server.shutdown to the configuration file. Either immediate or graceful shutdown is graceful.

image-20200624095818220
server:
  port: 8081
  shutdown: graceful

The method defined above has a delay of 6 seconds, so 10 seconds is definitely enough
spring:  lifecycle:  timeout-per-shutdown-phase: 10s Copy the code

After that, start the service again, and then visit the page, terminating the process. You will then see output from the console indicating a graceful shutdown and waiting for active request processing to complete.

image-20200624103229034

Requests become normal.

image-20200624103359637

Activity detection

In previous versions of the Spring-boot-starter actuator, health detection is already available and activity detection is not enabled. When we access health, we see the following information indicating that the service is available.

image-20200624113746766

You can enable active status detection by configuring the following information in the configuration file.

management:
  health:
    probes:
      enabled: true
 endpoint:
 health:  show-details: always Copy the code

After the preceding configuration is enabled and the service is restarted, the following information is displayed on the Health page

image-20200624114306674

In addition to status, there is a groups node.

Liveness: Whether the application is available

Can see through/physical/health/liveness path

image-20200624114517046

Readiness: Whether the application is ready to accept client requests.

Can see through/physical/health/readiness path

image-20200624114631242

This feature is designed to support services deployed on Kubernetes. Kubernetes provides LivenessProbe and cProbe, and active status checks provide seamless support for both types of probes.

Add the configuration in the configuration file, and make seamless connection with Kubernetes.

spring:
  main:
    cloud-platform: kubernetes
Copy the code

So how does that work

Take Readiness for example. Suppose we want to announce that the service will not accept requests for the time being. Then change the Readiness state.

So to do that, I added two methods to the Controller, one to start accepting requests and one to stop accepting requests.

@RestController
public class PlayController {

    private final ApplicationEventPublisher publisher;

 public PlayController(ApplicationEventPublisher publisher) {  this.publisher = publisher;  }   @GetMapping(value = "play")  public String play(a) throws InterruptedException{  Thread.sleep(6000);  return "hey, play with me!";  }   @GetMapping(value = "up")  public String up(a){  AvailabilityChangeEvent.publish(publisher,this, ReadinessState.ACCEPTING_TRAFFIC);  return "up";  }   @GetMapping(value = "down")  public String down(a){  AvailabilityChangeEvent.publish(publisher,this, ReadinessState.REFUSING_TRAFFIC);  return "down";  } } Copy the code

Change the status of the service using the Publish method of the AvailabilityChangeEvent class. After accessing the Down interface, the health/ Readiness status is checked again. The following information is displayed: OUT_OF_SERVICE Indicates that the server is offline and does not accept requests.

image-20200624120041609

When we request the UP interface, the service status changes to Up again, which realizes the offline and online functions of the service.

Support the JDK 14

Spring Boot 2.3 supports JDK 14, but does it matter to me? I still use my Java 8. Smells good.

Spring Data Neumann

Spring Boot 2.3 released Spring Data Neumann, which includes many major releases and driver upgrades. This release also adds stable version support for R2DBC (Reactive Relational Database Connectivity). R2DBC provides asynchronous programming access to the database API, is mainly used with the development of asynchronous non-blocking applications.

conclusion

It can be seen that a large part of the content is related to Docker container technology, such as layered image package, seamless support for Kubernetes, etc. It can be seen that Docker micro-service has become the choice of many developers. However, there are still some improvements to be made. For example, the default Docker Hub is Google Cloud, so it cannot be flexibly configured to support the domestic mirror warehouse.

What version of Spring Boot do you use and will you try it?

Reference Documents:

https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/maven-plugin/reference/html/index.html#goals

https://medium.com/@TimvanBaarsen/whats-new-in-spring-boot-2-3-22d01d036f11


Strong man wait, first give a praise bar, always white piao, the body can not bear!

I am kite, the official number “ancient kite”. A programmer with both depth and breadth of encouragement teacher, a intended to write poetry but write up the code of rural code farmers! You can follow me now, or you can follow history articles later.