[Microservice] Dựng Microservice web bằng Spring Boot và Eureka [Phần 1]

Chúng tôi vui mừng chia sẻ kiến thức về từ khóa Eureka la gi và hy vọng rằng nó sẽ hữu ích cho bạn đọc. Bài viết tập trung trình bày ý nghĩa, vai trò và ứng dụng của từ khóa này trong việc tối ưu hóa nội dung trang web và chiến dịch tiếp thị trực tuyến. Chúng tôi cung cấp các phương pháp tìm kiếm, phân tích và lựa chọn từ khóa phù hợp, cùng với các chiến lược và công cụ hữu ích. Hy vọng rằng thông tin mà chúng tôi chia sẻ sẽ giúp bạn xây dựng chiến lược thành công và thu hút lưu lượng người dùng. Xin chân thành cảm ơn sự quan tâm và hãy tiếp tục theo dõi blog của chúng tôi để cập nhật những kiến thức mới nhất.

Microservices là một giải pháp được chấp nhận chia một mạng lưới hệ thống lớn thành một vài các component độc lập về phát triển, test và deploy.

Bạn Đang Xem: [Microservice] Dựng Microservice web bằng Spring Boot và Eureka [Phần 1]

Spring Cloud là một dự án con trong họ nhà Spring, được sử dụng để phát triển các ứng dụng phân tán. Một ứng dụng được gọi là phần tán (Distributed application) lúc các phần của nó có thể được phát triển trên các tiếng nói khác nhau và được triển khai trên các sever khác nhau. Như vậy, Spring Cloud sinh ra là để làm các mạng lưới hệ thống microservice. Tất cả những dự sán Spring Cloud nên được tạo từ Spring Boot để giảm thiểu các cấu hình phức tạp và dễ thiết lập hơn.

Trong series này, tất cả chúng ta sẽ cùng tìm hiểu cách xây dựng một mạng lưới hệ thống microservice bằng Spring Boot và Eureka (một dự án trong Spring Cloud). Phần trước tiên là tạo các microservice và gateway.

img_1

Nhìn vào sơ đồ các thành phần của mạng lưới hệ thống ở trên, tất cả chúng ta cần tạo các service registry, image, gallery và một gateway. Gallery service sẽ sử dụng những tấm hình lấy từ Image service và sắp xếp chúng thành một album hình ảnh.

Phiên bản Spring Boot mà tất cả chúng ta sẽ sử dụng trong serries này là 2.0.0.RELEASE.

<parentvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-parentvàlt;/artifactIdvàgt; <versionvàgt;2.0.0.RELEASEvàlt;/versionvàgt; <relativePath/> </parentvàgt;

Đây là một sever dùng làm quản lý, đặt tên cho những service, hay còn gọi là service registry. Nhưng vì sao tất cả chúng ta lại cần một server để tại vị tên cho từng service. Lý do:

  • Tất cả chúng ta không muốn hardcode địa chỉ IP của mỗi microservice. Bạn chẳng bao giờ dùng địa chỉ 64.233.181.99 để truy cập vào trang google.com, đúng chứ?
  • Khi mà các service của tất cả chúng ta sử dụng IP động, nó sẽ tự động hóa update, tất cả chúng ta không cần thay đổi code.

Vậy là mỗi service sẽ tiến hành đăng ký với Eureka và sẽ ping cho Eureka để đảm bảo chúng vẫn hoạt động. Nếu Eureka server không sở hữu và nhận được bất kỳ thông tin nào từ service thì service này sẽ bị gỡ khỏi Eureka một cách tự động hóa.

Ok, để tạo Eureka server, tất cả chúng ta sẽ dùng Maven để quản lý các dependencies. Lưu ý khác với kiến trúc monolithic, mỗi component trong microservice được dựng một cách độc lập. Do đó tất cả chúng ta sẽ tạo mới một project Spring Boot và khai báo file pom.xml có những dependencies Web, Eureka Server và DevTools (tùy chọn):

<dependenciesvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-webvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.cloudvàlt;/groupIdvàgt; <artifactIdvàgt;spring-cloud-starter-netflix-eureka-servervàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-devtoolsvàlt;/artifactIdvàgt; <scopevàgt;runtimevàlt;/scopevàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-testvàlt;/artifactIdvàgt; <scopevàgt;testvàlt;/scopevàgt; </dependencyvàgt; </dependenciesvàgt;

Tiếp theo, trong file application.properties, tất cả chúng ta cần cấu hình một số thứ như sau:

# Give a name to the eureka server spring.application.name=eureka-server # default port for eureka server server.port=8761 # eureka by default will register itself as a client. So, we need to set it to false. # What’s a client server? See other microservices (image, gallery, auth, etc). eureka.client.register-with-eureka=false eureka.client.fetch-registry=false

Cuối cùng, trong class main của project, tất cả chúng ta sẽ khai báo đây là một Eureka server bằng annotation @EnableEurekaServer:

package io.github.tubean.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); } }

Đơn giản thế thôi, đi tiếp đến những service về nghiệp vụ nào 😄

Các Eureka client service là một service độc lập trong kiến trúc microservice. Mỗi client service chỉ thực hiện duy nhất một nghiệp vụ nào đó trong mạng lưới hệ thống như tính sổ, tài khoản, thông tin, xác thực, cấu hình,… Tất cả chúng ta sẽ xây dựng dựng image service như một nguồn để chứa và cung cấp các tấm hình, mỗi tấm hình sẽ sở hữu được id, title và địa chỉ url. Chỉ đơn giản như vậy thôi.

Ok, cũng như Eureka Server, tất cả chúng ta sẽ tạo một project Spring Boot mới nhưng sử dụng Eureka Client trong file pom.xml:

Xem Thêm : GREAT BRITAIN LÀ NƯỚC NÀO

<dependenciesvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-webvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.cloudvàlt;/groupIdvàgt; <artifactIdvàgt;spring-cloud-starter-netflix-eureka-clientvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-data-restvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-devtoolsvàlt;/artifactIdvàgt; <scopevàgt;runtimevàlt;/scopevàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-testvàlt;/artifactIdvàgt; <scopevàgt;testvàlt;/scopevàgt; </dependencyvàgt; </dependenciesvàgt;

Trong file appication.properties tất cả chúng ta sẽ ghi lại địa chỉ của Eureka server:

# serivce name spring.application.name=image-service # port server.port=8200 # eureka server url eureka.client.service-url.default-zone=http://localhost:8761/eureka

Sau đó để chỉ cho Spring Boot biết đây là một Eureka client, tất cả chúng ta dùng annotation @EnableEurekaClient trong class main:

package io.github.tubean.eureka.image; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class ImageApplication { public static void main(String[] args) { SpringApplication.run(ImageApplication.class, args); } }

Lúc này để image service có thể expose data ra ngoài, tất cả chúng ta cần có những endpoint đúng không nhỉ? Tương tự một RESTful web service, tất cả chúng ta sẽ tạo một entity khái niệm cấu trúc chuỗi JSON và một controller điều phối:

  • Image.java

package io.github.tubean.eureka.image.entity; public class Image { private Integer id; private String title; private String url; public Image(Integer id, String title, String url) { this.id = id; this.title = title; this.url = url; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }

  • HomeController.java

package io.github.tubean.eureka.image.controller; import io.github.tubean.eureka.image.entity.Image; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; import java.util.List; @RestController @RequestMapping(“/”) public class HomeController { @Autowired private Environment env; @RequestMapping(“/”) public String home() { // This is useful for debugging // When having multiple instance of image service running at different ports. // We load balance among them, and display which instance received the request. return “Hello from Image Service running at port: ” + env.getProperty(“local.server.port”); } @RequestMapping(“/images”) public Listvàlt;Imagevàgt; getImages() { Listvàlt;Imagevàgt; images = Arrays.asList( new Image(1, “Treehouse of Horror V”, “https://www.imdb.com/title/tt0096697/mediaviewer/rm3842005760”), new Image(2, “The Town”, “https://www.imdb.com/title/tt0096697/mediaviewer/rm3698134272”), new Image(3, “The Last Traction Hero”, “https://www.imdb.com/title/tt0096697/mediaviewer/rm1445594112”)); return images; } }

Các Eureka client service có thể là một REST client dùng làm cung cấp data cho một service khác (REST API service). Do đó, trong mạng lưới hệ thống của tất cả chúng ta, gallery service sẽ gọi đến image service thông qua các endpoint mà tất cả chúng ta đã tạo ra ở trên, và từ này sẽ get ra một list ảnh để tạo ra một album. Để gọi đến một service từ một REST client, tất cả chúng ta có thể sử dụng:

  1. RestTemplate: Đây là một object được chấp nhận gửi request đến một REST API service.
  2. FeignClient: hoạt động như một proxy, cung cấp các giải pháp khác cho RestTemplate.

Và cả hai cách thì cân bằng tải đều phải sở hữu thể ứng dụng.

Cân bằng tải (Load balancing) là gì? Nếu như có nhiều hơn một instance của một service chạy trên các port khác nhau thì tất cả chúng ta cần cân bằng những request giữa tất cả những instance đó. Trong tham dự lý tưởng thì cân bằng tải sẽ giúp các port nhận số lượng request tương đương nhau.

Tương tự Image service, tất cả chúng ta khai báo file pom.xml cho Gallery service. Và trong application.properties, port sử dụng sẽ khác với Image service:

spring.application.name=gallery-service server.port=8100 eureka.client.service-url.default-zone=http://localhost:8761/eureka

Trong class main, bên cạnh annotation @EnableEurekaClient, tất cả chúng ta sẽ cần tạo thêm một bean cho RestTemplate dùng làm gọi đến image service.

package io.github.tubean.eureka.gallery; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableEurekaClient public class GalleryServiceApplication { public static void main(String[] args) { SpringApplication.run(GalleryServiceApplication.class, args); } } @Configuration class RestTemplateConfig { // Create a bean for restTemplate to call services @Bean @LoadBalanced // Load balance between service instances running at different ports. public RestTemplate restTemplate() { return new RestTemplate(); } }

Hãy nhờ rằng entity và controller:

  • Gallery.java

package io.github.tubean.eureka.gallery.entity; import java.util.List; public class Gallery { private Integer id; private Listvàlt;Objectvàgt; images; public Gallery(Integer id, Listvàlt;Objectvàgt; images) { this.id = id; this.images = images; } public Gallery() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Listvàlt;Objectvàgt; getImages() { return images; } public void setImages(Listvàlt;Objectvàgt; images) { this.images = images; } }

  • HomeController.java

package io.github.tubean.eureka.gallery.controller; import io.github.tubean.eureka.gallery.entity.Gallery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @RequestMapping(“/”) public class HomeController { @Autowired private RestTemplate restTemplate; @Autowired private Environment env; @RequestMapping(“/”) public String home() { // This is useful for debugging // When having multiple instance of gallery service running at different ports. // We load balance among them, and display which instance received the request. return “Hello from Gallery Service running at port: ” + env.getProperty(“local.server.port”); } @RequestMapping(“/{id}”) public Gallery getGallery(@PathVariable final int id) { // create gallery object Gallery gallery = new Gallery(); gallery.setId(id); // get list of available images Listvàlt;Objectvàgt; images = restTemplate.getForObject(“http://image-service/images/”, List.class); gallery.setImages(images); return gallery; } // – Admin Area – // This method should only be accessed by users with role of ‘admin’ // We’ll add the logic of role based auth later @RequestMapping(“/admin”) public String homeAdmin() { return “This is the admin area of Gallery service running at port: ” + env.getProperty(“local.server.port”); } }

Ok, đến đây tất cả chúng ta cần lưu ý khi sử dụng restTemplate thì trong Eureka Server đã đặt tên cho những service nên tất cả chúng ta sẽ sử dụng tên của chúng (image-service thay vì localhost:port) nhằm mục tiêu sử dụng cân bằng tải.

Khi tất cả chúng ta gọi đến bất kỳ service nào từ browser, tất cả chúng ta không thể gọi trực tiếp bằng tên của chúng như ở trên Gallery server đã làm bởi vì những tên service như vậy phải được kín đáo và chỉ sử dụng trong nội bộ các service với nhau.

Xem Thêm : Thủ tục và sử dụng Dextrostix trong sơ sinh / Thuốc | Thpanorama – Làm cho mình tốt hơn ngày hôm nay!

Nếu tất cả chúng ta có nhiều instance của một service, mỗi instance lại sử dụng một port khác nhau. Vậy làm thế nào tất cả chúng ta có thể gọi tất cả những service từ browser và phân tán những request đến những instance đó thông qua các cổng khác nhau? Câu vấn đáp là sử dụng một Gateway.

Một gateway là một entry point đơn trong mạng lưới hệ thống, được dùng làm handle các request bằng phương pháp định tuyến chúng đến những service tương ứng. Nó cũng luôn tồn tại thể được dùng làm xác thực, giám sát và làm nhiều việc khác.

Zuul là gì?

Nó là một proxy, gateway và một lớp trung gian giữa user và các service của bạn. Eureka server đã giải quyết và xử lý việc đặt tên cho từng service thay vì dùng địa chỉ IP của chúng. Tuy nhiên một service vẫn có thể có nhiều instance và chúng sẽ chạy trên các cổng khác nhau nên nhiệm vụ của Zuul sẽ là:

  • Map giữa một prefix path (/gallery/**) và một service (gallery-service). Nó sử dụng Euraka server để định tuyến các service được request.
  • Nó giúp cân bằng tải giữa các instance của một service.
  • Còn gì nữa? Tất cả chúng ta có thể dùng nó để filter request, thêm xác thực,…

Trong file pom.xml của project Zuul, tất cả chúng ta sẽ có những dependencies: Web, Eureka Client và Zuul:

<dependenciesvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-webvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.cloudvàlt;/groupIdvàgt; <artifactIdvàgt;spring-cloud-starter-netflix-zuulvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.cloudvàlt;/groupIdvàgt; <artifactIdvàgt;spring-cloud-starter-netflix-eureka-clientvàlt;/artifactIdvàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-devtoolsvàlt;/artifactIdvàgt; <scopevàgt;runtimevàlt;/scopevàgt; </dependencyvàgt; <dependencyvàgt; <groupIdvàgt;org.springframework.bootvàlt;/groupIdvàgt; <artifactIdvàgt;spring-boot-starter-testvàlt;/artifactIdvàgt; <scopevàgt;testvàlt;/scopevàgt; </dependencyvàgt; </dependenciesvàgt;

Điều đáng nói là Zuul hoạt động như một Eureka client. Vì vậy tất cả chúng ta có thể đặt tên cho nó, chỉ định port và đường dẫn đến Eureka server như các client trước đó.

server.port=8762 spring.application.name=zuul-server eureka.client.service-url.default-zone=http://localhost:8761/eureka/ # A prefix that can added to beginning of all requests. #zuul.prefix=/api # Disable accessing services using service name (i.e. gallery-service). # They should be only accessed through the path defined below. zuul.ignored-services=* # Map paths to services zuul.routes.gallery-service.path=/gallery/** zuul.routes.gallery-service.service-id=gallery-service

Cuối cùng là thêm các annotation để thông tin đây là Zuul và Eureka client:

package io.github.tubean.eureka.zuulserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableEurekaClient // It acts as a eureka client @EnableZuulProxy // Enable Zuul public class ZuulServerApplication { public static void main(String[] args) { SpringApplication.run(ZuulServerApplication.class, args); } }

Ok, như vậy là tất cả chúng ta đã dựng xong bộ sườn cho mạng lưới hệ thống microservice. Tất cả chúng ta đã có một service discovery (Eureka server), hai service (Image và Gallery), một cổng gateway (Zuul) và giờ chỉ có start chúng lên.

Để chạy nhiều instance thì trong Eclipse, bạn vào Run -> Configurations/Arguments -> VM options và thêm -Dsever.port=8300

Để kiểm tra ứng dụng của tất cả chúng ta, hãy truy cập vào localhost:8761, đây là cổng của Eureka Server. Và các bạn sẽ thấy các server đang hoạt động như sau: img_3 Sau đó hãy gọi tiếp đến gallery service bằng đường dẫn localhost:8762/gallery. Tất cả chúng ta sẽ nhận được message như sau: >Hello from Gallery Service running at port: 8100

Nếu dùng multiple instance, các bạn sẽ nhận được 2 dòng như trên với 2 cổng khác nhau.

Tiếp theo tất cả chúng ta gọi đến service Image thông qua Gallery bằng đường dẫn localhost:8762/gallery/1. Kết quả nhận được sẽ là:

// 20181218230927 // http://localhost:8762/gallery/1 { “id”: 1, “images”: [ { “id”: 1, “title”: “Treehouse of Horror V”, “url”: “https://www.imdb.com/title/tt0096697/mediaviewer/rm3842005760” }, { “id”: 2, “title”: “The Town”, “url”: “https://www.imdb.com/title/tt0096697/mediaviewer/rm3698134272” }, { “id”: 3, “title”: “The Last Traction Hero”, “url”: “https://www.imdb.com/title/tt0096697/mediaviewer/rm1445594112” } ] }

Kết thúc phần trước tiên ở đây, ở phần tiếp theo tất cả chúng ta sẽ tìm hiểu phương pháp để xác thực user bằng JWT.

https://tubean.github.io/2018/12/microservice-springboot-eureka-part2/

https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-intro-to-microservices-part-1-c0d24cd422c3

https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-creating-our-microserivces-gateway-part-2-31f8aa6b215b

https://github.com/tubean/MSA-springboot-eureka

You May Also Like

About the Author: v1000

tỷ lệ kèo trực tuyến manclub 789club