Metodologi Dua Belas Faktor dalam Perkhidmatan Mikro Boot Musim Semi

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan memahami metodologi aplikasi dua belas faktor.

Kami juga akan memahami bagaimana mengembangkan perkhidmatan mikro dengan bantuan Spring Boot. Dalam prosesnya, kita akan melihat bagaimana menerapkan metodologi dua belas faktor untuk mengembangkan perkhidmatan mikro seperti itu.

2. Apakah Metodologi Faktor Dua Belas?

Metodologi dua belas faktor adalah satu set dua belas amalan terbaik untuk mengembangkan aplikasi yang dikembangkan untuk dijalankan sebagai perkhidmatan . Ini pada awalnya dirancang oleh Heroku untuk aplikasi yang digunakan sebagai perkhidmatan di platform cloud mereka, pada tahun 2011. Seiring berjalannya waktu, ini terbukti cukup generik untuk sebarang pengembangan perisian-sebagai-perkhidmatan (SaaS).

Jadi, apa yang kita maksudkan dengan perisian-sebagai-perkhidmatan? Secara tradisional kami merancang, mengembangkan, menggunakan, dan mengekalkan penyelesaian perisian untuk mendapatkan nilai perniagaan darinya. Tetapi, kita tidak perlu terlibat dalam proses ini untuk mencapai hasil yang sama. Sebagai contoh, mengira cukai yang berlaku adalah fungsi umum dalam banyak domain.

Sekarang, kami mungkin memutuskan untuk membangun dan mengurus perkhidmatan ini sendiri atau melanggan tawaran perkhidmatan komersial . Penawaran perkhidmatan seperti itu adalah apa yang kita ketahui sebagai perisian-sebagai-perkhidmatan .

Walaupun perisian-sebagai-perkhidmatan-tidak memberi sekatan pada seni bina yang dibangunkan; agak berguna untuk mengamalkan beberapa amalan terbaik.

Sekiranya kita merancang perisian kita menjadi modular, mudah alih, dan dapat diskalakan pada platform awan moden, ini sangat sesuai dengan penawaran perkhidmatan kami. Di sinilah kaedah metodologi dua belas faktor membantu. Kami akan melihatnya beraksi kemudian dalam tutorial.

3. Perkhidmatan Mikro dengan Spring Boot

Microservice adalah gaya seni bina untuk mengembangkan perisian sebagai perkhidmatan yang digabungkan secara longgar. Keperluan utama di sini adalah bahawa perkhidmatan harus disusun di sekitar sempadan domain perniagaan . Ini adalah bahagian yang paling sukar untuk dikenal pasti.

Lebih-lebih lagi, perkhidmatan di sini mempunyai satu-satunya kuasa atas datanya dan mendedahkan operasi kepada perkhidmatan lain. Komunikasi antara perkhidmatan biasanya melebihi protokol ringan seperti HTTP. Ini menghasilkan perkhidmatan yang dapat disebarkan dan diskalakan secara bebas.

Kini, seni bina perkhidmatan mikro dan perisian tidak bergantung pada satu sama lain. Tetapi, tidak sukar untuk difahami bahawa, ketika mengembangkan perisian sebagai perkhidmatan, memanfaatkan seni bina perkhidmatan mikro cukup bermanfaat . Ini membantu mencapai banyak matlamat yang telah kita bincangkan sebelumnya, seperti modulariti dan skalabiliti.

Spring Boot adalah kerangka aplikasi berdasarkan Spring yang menghilangkan banyak boilerplate yang berkaitan dengan pengembangan aplikasi perusahaan. Ini memberi kita platform yang sangat berpandangan tetapi fleksibel untuk mengembangkan perkhidmatan mikro. Untuk tutorial ini, kami akan memanfaatkan Spring Boot untuk menyampaikan perkhidmatan mikro menggunakan metodologi dua belas faktor.

4. Mengaplikasikan Metodologi Faktor Dua Belas

Sekarang mari kita tentukan aplikasi mudah yang akan kita cuba kembangkan dengan alat dan amalan yang baru kita bincangkan. Kita semua gemar menonton filem, tetapi mencabar untuk menonton filem yang telah kita tonton.

Sekarang, siapa yang mahu memulakan filem dan kemudian membuangnya kemudian? Apa yang kami perlukan adalah perkhidmatan mudah untuk merakam dan menyoal filem yang telah kami tonton:

Ini adalah perkhidmatan mikro yang sederhana dan standard dengan penyimpanan data dan titik akhir REST. Kita perlu menentukan model yang akan memetakan ketekunan juga:

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

Kami telah menentukan entiti JPA dengan id dan beberapa atribut lain. Sekarang mari kita lihat seperti apa pengawal REST:

@RestController public class MovieController { @Autowired private MovieRepository movieRepository; @GetMapping("/movies") public List 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(); } }

Ini merangkumi asas perkhidmatan mudah kami. Kami akan melalui aplikasi selebihnya semasa kami membincangkan bagaimana kami melaksanakan metodologi dua belas faktor dalam bahagian berikut.

4.1. Pangkalan Kod

Amalan terbaik pertama aplikasi dua belas faktor adalah mengesannya dalam sistem kawalan versi. Git adalah sistem kawalan versi paling popular yang digunakan sekarang dan hampir di mana-mana. Prinsip tersebut menyatakan bahawa aplikasi harus dijejaki dalam repositori kod tunggal dan tidak boleh berkongsi repositori itu dengan aplikasi lain .

Spring Boot menawarkan banyak cara mudah untuk bootstrap aplikasi, termasuk alat baris perintah dan antara muka web. Sebaik sahaja kami menghasilkan aplikasi bootstrap, kami dapat mengubahnya menjadi git repositori:

git init

Perintah ini harus dijalankan dari akar aplikasi. Aplikasi pada tahap ini sudah mengandungi fail .gitignore yang secara efektif menyekat fail yang dihasilkan daripada dikendalikan versi. Oleh itu, kita boleh membuat komit awal:

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

Akhirnya, kita dapat menambahkan alat kawalan jauh dan mendorong komit kita ke jarak jauh jika kita mahu (ini bukan syarat yang ketat):

git remote add origin //github.com//12-factor-app.git git push -u origin master

4.2. Kebergantungan

Seterusnya, aplikasi dua belas faktor harus selalu menyatakan secara jelas semua kebergantungannya . Kita harus melakukan ini menggunakan manifes pergantungan pergantungan. Java mempunyai pelbagai alat pengurusan pergantungan seperti Maven dan Gradle. Kita boleh menggunakan salah satunya untuk mencapai matlamat ini.

Oleh itu, aplikasi mudah kami bergantung pada beberapa perpustakaan luaran, seperti perpustakaan untuk memudahkan API REST dan menyambung ke pangkalan data. Mari kita lihat bagaimana kita dapat mendefinisikannya secara Murni menggunakan Maven.

Maven menghendaki kita menerangkan kebergantungan projek dalam fail XML, biasanya dikenali sebagai Project Object Model (POM):

  org.springframework.boot spring-boot-starter-web   com.h2database h2 runtime  

Walaupun ini kelihatan jelas dan sederhana, pergantungan ini biasanya mempunyai pergantungan transitif yang lain. Ini menyukarkannya sehingga membantu kita mencapai matlamat kita. Sekarang, aplikasi kita tidak mempunyai kebergantungan langsung yang tidak dijelaskan secara eksplisit.

4.3. Konfigurasi

Aplikasi biasanya mempunyai banyak konfigurasi, beberapa di antaranya mungkin berbeza antara penyebaran sementara yang lain tetap sama.

Dalam contoh kami, kami mempunyai pangkalan data yang berterusan. Kami memerlukan alamat dan kelayakan pangkalan data untuk disambungkan. Ini kemungkinan besar akan berubah antara penyebaran.

Aplikasi dua belas faktor harus mengeksternalisasi semua konfigurasi sedemikian yang berbeza antara penerapan . Cadangan di sini adalah menggunakan pemboleh ubah persekitaran untuk konfigurasi tersebut. Ini membawa kepada pemisahan konfigurasi dan kod yang bersih.

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 { }

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  -it 

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

A twelve-factor app is expected 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.

In the case of our example, we've got multiple endpoints exposed. A request on any of these endpoints is entirely independent of any request made before it. For instance, if we keep track of user requests in-memory and use that information to serve future requests, it violates a twelve-factor app.

Hence, a twelve-factor app imposes no such restriction like sticky sessions. This makes such an app highly portable and scalable. In a cloud execution environment offering automated scaling, it's quite a desirable behavior from applications.

4.7. Port Binding

A traditional web application in Java is developed as a WAR or web archive. This is typically a collection of Servlets with dependencies, and it expects a conformant container runtime like Tomcat. A twelve-factor app, on the contrary, expects no such runtime dependency. It's completely self-contained and only requires an execution runtime like Java.

In our case, we've developed an application using Spring Boot. Spring Boot, apart from many other benefits, provides us with a default embedded application server. Hence, the JAR we generated earlier using Maven is fully capable of executing in any environment just by having a compatible Java runtime:

java -jar application.jar

Here, our simple application exposes its endpoints over an HTTP binding to a specific port like 8080. Upon starting the application as we did above, it should be possible to access the exported services like HTTP.

An application may export multiple services like FTP or WebSocket by binding to multiple ports.

4.8. Concurrency

Java offers Thread as a classical model to handle concurrency in an application. Threads are like lightweight processes and represent multiple paths of execution in a program. Threads are powerful but have limitations in terms of how much it can help an application scale.

The twelve-factor methodology suggests apps to rely on processes for scaling. What this effectively means is that applications should be designed to distribute workload across multiple processes. Individual processes are, however, free to leverage a concurrency model like Thread internally.

A Java application, when launched gets a single process which is bound to the underlying JVM. What we effectively need is a way to launch multiple instances of the application with intelligent load distribution between them. Since we've already packaged our application as a Docker container, Kubernetes is a natural choice for such orchestration.

4.9. Disposability

Application processes can be shut down on purpose or through an unexpected event. In either case, a twelve-factor app is supposed to handle it gracefully. In other words, an application process should be completely disposable without any unwanted side-effects. Moreover, processes should start quickly

For instance, in our application, one of the endpoints is to create a new database record for a movie. Now, an application handling such a request may crash unexpectedly. This should, however, not impact the state of the application. When a client sends the same request again, it shouldn't result in duplicate records.

In summary, the application should expose idempotent services. This is another very desirable attribute of a service destined for cloud deployments. This gives the flexibility to stop, move, or spin new services at any time without any other considerations.

4.10. Dev/Prod Parity

It's typical for applications to be developed on local machines, tested on some other environments and finally deployed to production. It's often the case where these environments are different. For instance, the development team works on Windows machines whereas production deployment happens on Linux machines.

The twelve-factor methodology suggests keeping the gap between development and production environment as minimal as possible. These gaps can result from long development cycles, different teams involved, or different technology stack in use.

Now, technology like Spring Boot and Docker automatically bridge this gap to a great extent. A containerized application is expected to behave the same, no matter where we run it. We must use the same backing services – like the database – as well.

Moreover, we should have the right processes like continuous integration and delivery to facilitate bridging this gap further.

4.11. Logs

Logs are essential data that an application generates during its lifetime. They provide invaluable insights into the working of the application. Typically an application can generate logs at multiple levels with varying details and output ii in multiple different formats.

A twelve-factor app, however, separates itself from log generation and its processing. For such an app, logs are nothing but a time-ordered stream of events. It merely writes these events to the standard output of the execution environment. The capture, storage, curation, and archival of such stream should be handled by the execution environment.

There are quite several tools available to us for this purpose. To begin with, we can use SLF4J to handle logging abstractly within our application. Moreover, we can use a tool like Fluentd to collect the stream of logs from applications and backing services.

This we can feed into Elasticsearch for storage and indexing. Finally, we can generate meaningful dashboards for visualization in Kibana.

4.12. Admin Processes

Often we need to perform some one-off tasks or routine procedure with our application state. For instance, fixing bad records. Now, there are various ways in which we can achieve this. Since we may not often require it, we can write a small script to run it separately from another environment.

Now, the twelve-factor methodology strongly suggests keeping such admin scripts together with the application codebase. In doing so, it should follow the same principles as we apply to the main application codebase. It's also advisable to use a built-in REPL tool of the execution environment to run such scripts on production servers.

In our example, 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. Practical Applications

So, now we've seen all the factors suggested by the twelve-factor methodology. Developing an application to be a twelve-factor app certainly has its benefits, especially when we wish to deploy them as services on the cloud. But, like all other guidelines, framework, patterns, we must ask, is this a silver bullet?

Honestly, no single methodology in software design and development claim to be a silver bullet. The twelve-factor methodology is no exception. While some of these factors are quite intuitive, and most likely we're already doing them, others may not apply to us. It's essential to evaluate these factors in the backdrop of our objectives and then choose wisely.

It's important to note that all these factors are there to help us develop an application which is modular, independent, portable, scalable, and observable. Depending upon the application, we may be able to achieve them through other means better. It's also not necessary to adopt all the factors together, adopting even some of these may make us better than we were.

Finally, these factors are quite simple and elegant. They hold greater importance in an age where we demand our applications to have higher throughput and lower latency with virtually no downtime and failure. Adopting these factors gives us the right start from the beginning. Combined with microservice architecture and containerization of applications, they just seem to hit the right spot.

6. Conclusion

Dalam tutorial ini, kami membahas konsep metodologi dua belas faktor. Kami membincangkan bagaimana memanfaatkan seni bina perkhidmatan mikro dengan Spring Boot untuk menyampaikannya dengan berkesan. Selanjutnya, kami meneroka setiap faktor secara terperinci dan bagaimana menerapkannya ke aplikasi kami. Kami juga meneroka beberapa alat untuk menerapkan faktor-faktor individu ini dengan cara yang berkesan dengan jayanya.