Spring Boot 微服務十二要素方法論

Architecture,REST,Spring Boot
Remote
1
08:35 AM · Dec 01 ,2025

1. 概述

在本教程中,我們將理解 十二要素應用程序方法論

我們還將瞭解如何使用 Spring Boot 開發微服務。 在此過程中,我們將看到如何將十二要素方法論應用於開發此類微服務。

2. 十二要素方法論是什麼?

十二要素方法論是一套十二個最佳實踐,用於開發能夠作為服務運行的應用。 這最初由 Heroku 為了在他們的雲平台上部署的服務應用而編寫的,早在 2011 年就完成了。 隨着時間的推移,它已經足夠通用,可以用於任何 軟件即服務 (SaaS) 開發。

那麼,我們所説的軟件即服務是什麼意思? 傳統上,我們設計、開發、部署和維護軟件解決方案,以從這些解決方案中獲得業務價值。 但我們並不一定需要參與這個過程才能實現相同的結果。 例如,計算適用税額是許多領域中的一個通用函數。

現在,我們可能會決定自己構建和管理這個服務,或者 訂閲商業服務提供商。 這樣的 服務提供商 就是我們所説的軟件即服務。

雖然軟件即服務不限制其開發的架構,但採用一些最佳實踐仍然很有用。

如果我們設計我們的軟件,使其在現代雲平台上具有模塊化、可移植性和可擴展性,那麼它將非常適合我們的服務提供商。 這就是十二要素方法論發揮作用的地方。 我們稍後在教程中將看到它的實際應用。

3. 使用 Spring Boot 構建微服務

微服務是一種軟件架構風格,用於開發鬆耦合的服務。關鍵要求是 服務應圍繞業務領域邊界進行組織。 這通常是最難識別的部分。

此外,這裏的服務擁有對其數據的唯一權威,並向其他服務公開操作。服務之間的通信通常通過輕量級協議(如 HTTP)進行。 這導致了獨立部署和可擴展的服務。

現在,微服務架構和軟件即服務並非相互依賴。但是,很容易理解的是,在 開發軟件即服務時,利用微服務架構非常有益。 這有助於實現我們之前討論的許多目標,例如模塊化和可擴展性。

Spring Boot 是基於 Spring 的應用程序框架,它消除了開發企業應用程序相關的許多冗餘代碼。 它為我們提供了一個高度有意見但靈活的平台,用於開發微服務。 在本教程中,我們將利用 Spring Boot 使用十二要素方法來交付微服務。

4. Applying Twelve-Factor Methodology

Let’s now define a simple application that we’ll try to develop with the tools and practices we just discussed. We all love watching movies, but it’s challenging to keep track of the movies we’ve already watched.

Now, who would like to start a movie and then abandon it later? What we need is a simple service to record and query movies that we’ve watched:12 factpr app

This is quite a simple and standard microservice with a data store and REST endpoints. We need to define a model which will map to persistence as well:

@Entity
public class Movie {
    @Id
    private Long id;
    private String title;
    private String year;
    private String rating;
    // getters and setters
}

We’ve defined a JPA entity with an id and a few other attributes. Let’s now see what the REST controller looks like:

@RestController
public class MovieController {
    @Autowired
    private MovieRepository movieRepository;
    @GetMapping("/movies")
    public List<Movie> retrieveAllStudents() {
        return movieRepository.findAll();
    }

    @GetMapping("/movies/{id}")
    public Movie retrieveStudent(@PathVariable Long id) {
        return movieRepository.findById(id).get();
    }

    @PostMapping("/movies")
    public Long createStudent(@RequestBody Movie movie) {
        return movieRepository.save(movie).getId();
    }
}

This covers the base of our simple service. We’ll go through the rest of the application as we discuss how we implement the twelve-factor methodology in the following subsections.

4.1. Codebase

The first best practice of twelve-factor apps is to track it in a version control system. Git is the most popular version control system in use today and is almost ubiquitous. The principle states that an app should be tracked in a single code repository and must not share that repository with any other apps.

Spring Boot offers many convenient ways to bootstrap an application, including a command-line tool and a web interface. Once we generate the bootstrap application, we can convert this into a git repository:

git init

This command should be run from the root of the application. The application at this stage already contains a .gitignore file which effectively restricts generated files from being version-controlled. So, we can straight away create an initial commit:

git add .
git commit -m "Adding the bootstrap of the application."

Finally, we can add a remote and push our commits to the remote if we wish to (this is not a strict requirement):

git remote add origin https://github.com/<username>/12-factor-app.git
git push -u origin master

4.2. Dependencies

Next, the twelve-factor app should always explicitly declare all its dependencies. We should do this using a dependency declaration manifest. Java has multiple dependency management tools like Maven and Gradle. We can use one of them to achieve this goal.

So, our simple application depends on a few external libraries, like a library to facilitate REST APIs and to connect to a database. Let’s see how can we declaratively define them using Maven.

Maven requires us to describe a project’s dependencies in an XML file, typically known as Project Object Model (POM):

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Although this looks plain and simple, these dependencies usually have other transitive dependencies. This complicates it to an extent but helps us achieve our goal. Now, our application doesn’t have a direct dependency which is not explicitly described.

4.3. Configurations

An application typically has lots of configuration, some of which may vary between deployments while others remain the same.

In our example, we’ve got a persistent database. We’ll need the address and credentials of the database to connect to. This is most likely to change between deployments.

A twelve-factor app should externalize all such configurations that vary between deployments. The recommendation here is to use environment variables for such configurations. This leads to a clean separation of config and code.

Spring provides a configuration file where we can declare such configurations and attach it to environment variables:

spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/movies
spring.datasource.username=${MYSQL_USER}
spring.datasource.password=${MYSQL_PASSWORD}

Here, we’ve defined the database URL and credentials as configurations and have mapped the actual values to be picked from the environment variable.

On Windows, we can set the environment variable before starting the application:

set MYSQL_HOST=localhost
set MYSQL_PORT=3306
set MYSQL_USER=movies
set MYSQL_PASSWORD=password

We can use a configuration management tool like Ansible or Chef to automate this process.

4.4. Backing Services

Backing services are services that the application depends on for operation. For instance a database or a message broker. A twelve-factor app should treat all such backing services as attached resources. What this effectively means is that it shouldn’t require any code change to swap a compatible backing service. The only change should be in configurations.

In our application, we’ve used MySQL as the backing service to provide persistence.

Spring JPA makes the code quite agnostic to the actual database provider. We only need to define a repository which provides all standard operations:

@Repository
public interface MovieRepository extends JpaRepository<Movie, Long> {
}

As we can see, this is not dependent on MySQL directly. Spring detects the MySQL driver on the classpath and provides a MySQL-specific implementation of this interface dynamically. Moreover, it pulls other details from configurations directly.

So, if we’ve to change from MySQL to Oracle, all we’ve to do is replace the driver in our dependencies and replace the configurations.

4.5. Build, Release and Run

The twelve-factor methodology strictly separates the process of converting codebase into a running application as three distinct stages:

  • Build Stage: This is where we take the codebase, perform static and dynamic checks, and then generate an executable bundle like a JAR. Using a tool like Maven, this is quite trivial:
mvn clean compile test package
  • Release Stage: This is the stage where we take the executable bundle and combine this with the right configurations. Here, we can use Packer with a provisioner like Ansible to create Docker images:
packer build application.json
  • Run Stage: Finally, this is the stage where we run the application in a target execution environment. If we use Docker as the container to release our application, running the application can be simple enough:
docker run --name <container_id> -it <image_id>

Finally, we don’t necessarily have to perform these stages manually. This is where Jenkins comes in as pretty handy with their declarative pipeline.

4.6. Processes

The twelve-factor methodology suggests apps to run in an execution environment as stateless processes. In other words, they can not store persistent state locally between requests. They may generate persistent data which is required to be stored in one or more stateful backing services.

For instance, how do we seed our application with the already watched movies so far? While we can use our sweet little endpoint, but that may seem to be impractical. What we need is a script to perform a one-time load. We can write a small Java function to read a list of movies from a file and save them in batch into the database.

Moreover, we can use Groovy integrated with Java runtime to start such processes.

5. 實踐應用

因此,我們已經瞭解了十二要素方法的各項建議。開發一個符合十二要素應用的益處,尤其是在我們希望將它們作為雲服務部署時。但是,就像所有其他指南、框架和模式一樣,我們必須問自己,這是否是萬能鑰匙?

坦白説,沒有任何單一的設計和開發方法論聲稱是萬能鑰匙。十二要素方法論也不例外。雖然其中一些要素相當直觀,並且我們可能已經在使用它們,另一些要素可能不適用於我們。在考慮這些要素時,必須將其置於我們目標的背景下進行評估,然後明智地選擇。

重要的是要注意,所有這些要素都旨在幫助我們開發一個模塊化、獨立、可移植、可擴展和可觀察的應用程序。根據應用程序的不同,我們可能可以通過其他更有效的方式來實現它們。也不需要同時採用所有要素,即使採用其中的一些也能使我們比我們之前更好。

最後,這些要素非常簡單而優雅。在我們需要應用程序具有更高的吞吐量、更低的延遲以及幾乎沒有停機時間和故障的時代,這些要素變得更加重要。採用這些要素能幫助我們從一開始就獲得良好的開端。與微服務架構和應用程序容器化相結合,它們似乎正好擊中了要點。

6. 結論

在本教程中,我們探討了十二要素方法論的概念。我們討論瞭如何利用 Spring Boot 構建微服務架構來有效地實施這些要素。此外,我們對每個要素進行了詳細的探討,並瞭解如何將其應用於我們的應用程序。我們還探索了多種工具,以有效地實施這些要素。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.