Tìm hiểu về microservices, demonstration với SpringBoot

Chào mọi người, hôm nay mình sẽ tạo 1 demo nho nhỏ nhằm giới thiệu về microservices thông qua việc sử dụng SpringBoot. Đầu tiên ta tìm hiểu xem microservices là gì?

Microservices

Khi phát triển các hệ thống lớn, cách triển khai phổ biến nhất là phát triển hướng component và các lib khác nhau cái mà implement các chức năng khác nhau. Với cách này, một số thành phần được tái sử dụng bởi các giao diện và / hoặc hệ thống khác nhau. Hãy tưởng tượng, ví dụ, một component implement chức năng đăng ký user và chúng ta đóng gói component này thành 1 file jar rồi release.

Trong trường hợp này, chúng ta có thể có một số giao diện để sử dụng lại component này, chẳng hạn như các ứng dụng web, di động, EJB, v.v ...Ngoài ra vì là project Java, nên chúng ta có thể có nhiều lựa chọn đóng gói, chẳng hạn như EAR, WAR, v.v ...Hãy tưởng tượng bây giờ có vấn đề với gói đăng kí user. Lúc này, chúng ta sẽ tốn khá nhiều effort bao gồm cả việc fix issue này, và đặc biệt là sau khi hoàn thành việc fix issue, chúng ta sẽ phải thực hiện việc deploy lại tất cả các ứng dụng cái mà có component này được đóng gói bên trong.

Để tìm kiếm giải pháp cho vấn đề này, mô hình kiến trúc microservices đã ra đời. Trong mô hình kiến trúc này, thay vì gói các tệp tin jar vào các hệ thống tiêu dùng, các thành phần được tiếp xúc độc lập dưới dạng các API có thể truy cập từ xa, ví dụ như các giao thức như HTTP.

Một điểm quan trọng cần lưu ý là mặc dù chúng ta đang nói về các project của Java, nhưng những nguyên tắc tương tự cũng có thể được áp dụng cho các ngôn ngữ, ví dụ như C #.

Spring Boot

Là một trong những feature tuyệt vời của Spring framework, là cách nhanh nhất để tạo ra một REST service độc lập. Spring có hai benefit không thể bỏ qua:

  1. Nó đơn giản hóa việc cấu hình, cụ thể ở đây là Spring Boot tự cấu hình tất cả, bằng cách cung cấp các behaviour mặc định.
  2. Nó đơn giản hóa việc deploy, bằng cách đóng gói app của chúng ta thành gói jar, để có thể dễ dàng tích hợp vào các web container.

Không còn gì tuyệt vời hơn khi dùng Spring Boot cho kiến trúc microservices. Bắt đầu thôi 😃

Để minh họa cho khái niệm microservices, chúng ta sẽ tạo ra 3 dự án Maven trong đó: mỗi một trong số chúng sẽ tượng trưng cho chức năng back-end, nghĩa là các API có thể tái sử dụng lại, và một trong số chúng sẽ sử dụng 2 cái còn lại.

Để bắt đầu, ta tạo 3 project maven đơn giản được gọi là Menu, Customer, Order như là 3 REST services với Spring Boot bên trong. Cụ thể file pom.xml sẽ như sau

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
</dependencies>

Config cho 2 gói Menu và Customer là tương tự nhau

package tamnt.com.microservice.springboot.example;

import javax.inject.Named;

import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApplicationConfig {

	@Named
	static class JerseyConfig extends ResourceConfig {
		public JerseyConfig() {
			this.packages("tamnt.com.microservice.springboot.example.rest");
		}
	}

}

Gói Order config sẽ hơi khác so với 2 gói kia, vì nó sẽ gọi đến 2 REST services kia. Do đó ta cần khởi tạo thêm RestTemplate, class này là một trong những feature khá hay của Spring, chính nó đã làm cho việc 1 REST service này call đến những service khác trở nên cực kỳ đơn giản.

package tamnt.com.microservice.springboot.example;

import javax.inject.Named;

import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationConfig {

	@Named
	static class JerseyConfig extends ResourceConfig {
		public JerseyConfig() {
			this.packages("tamnt.com.microservice.springboot.example.rest");
		}
	}

	@Bean
	public RestTemplate restTemplate() {
		RestTemplate restTemplate = new RestTemplate();

		return restTemplate;
	}

}

Với 3 project hiện tại, chúng ta start service Customer ở port 8081, Menu ở port 8082 và Order ở port 8083. Dĩ nhiên mọi người có thể tuỳ chỉnh port này. Thuộc tính được sử dụng để cấu hình port là:

 -Dserver.port = 8081 

LƯU Ý: Nếu thay đổi các port thì phải sửa các port trong code implement của Order service ở dưới đây Code implement của class dưới đây chính là ví dụ tiêu biểu cho kiến trúc microservices. Cụ thể ở đây là trong REST của Order service sẽ gọi cả 2 service còn lại (là Customer và Menu) để lấy thông tin cần thiết ( thông qua RestTemplate). Dĩ nhiên với demo ở đây, chúng ta chỉ hardcode url gọi đến 2 service kia, trong thực tế tất nhiên sẽ khác đi. Một điều khá rõ ràng có thể nhận ra ở đây là việc maintenance khi có problem xảy ra với 1 trong 3 gói là rất đơn giản, không cần phải reploy tất cả các gói, mà chỉ cần gói nào xảy ra lỗi thì re-deploy lại gói đấy thôi.

 package tamnt.com.microservice.springboot.example.rest;

import java.util.Date;

import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.springframework.web.client.RestTemplate;

@Named
@Path("/")
public class OrderRest {

	private static long id = 1;

	@Inject
	private RestTemplate restTemplate;

	@GET
	@Path("order")
	@Produces(MediaType.APPLICATION_JSON)
	public Order submitOrder(@QueryParam("idCustomer") long idCustomer,
			@QueryParam("idMenu") long idMenu,
			@QueryParam("amount") long amount) {

		Order order = new Order();

		Customer customer = restTemplate.getForObject(
				"http://localhost:8081/customer?id={id}", Customer.class,
				idCustomer);

		Menu menu = restTemplate.getForObject(
				"http://localhost:8082/menu?id={id}", Menu.class,
				idMenu);

		order.setCustomer(customer);
		order.setMenu(menu);
		order.setId(id);
		order.setAmount(amount);
		order.setOrderDate(new Date());

		id++;

		return order;
	}
}

Sau khi đã start xong cả 3 gói service, thử gọi 1 request đơn giản nào

http://localhost:8083/order?idCustomer=2&idMenu=3&amount=4

Kết quả, ta nhận được 1 response dạng JSON như sau

{"id":1,"amount":4,"dateOrder":1419187358576,"customer":{"id":2,"name":"Customer 2","email":"[email protected]"},"menu":{"id":3,"sku":"abcd3","description":"Menu3"}}

Mọi người có thể tham khảo bằng cách checkout project mẫu của mình ở link github sau: https://github.com/tamnguyen201201/microservice-springboot-example

Tóm lược

Với việc triển khai đơn giản, nhưng mạnh mẽ, Spring Boot là một lựa chọn tốt để thực hiện kiến trúc microservices và nó đã được đánh giá qua các Architecture hay Technical Lead, thậm chí là Java developer, những người muốn thúc đẩy mô hình này trong nhu cầu của họ.


All Rights Reserved