Mình đã giới thiệu với các bạn về Microservices và những lợi ích to lớn mà nó mang lại. Quá trình xây dựng một ứng dụng theo kiểu Microservices sẽ có nhiều thử thách và một trong những thử thách đó là làm thế nào quản lý các service được tạo ra, bao gồm việc bảo trì, mở rộng và khả năng high availability của chúng. Ứng dụng càng lớn thì việc quản lý các service này sẽ lại càng khó khăn hơn.
Để giải quyết vấn đề này, người ta đã giới thiệu một khái niệm gọi là Service registration and discovery, nhằm định nghĩa một server, nơi có thể dùng để cho các service đăng ký và quản lý thông tin của chúng.
Server này sẽ chịu trách nhiệm lưu trữ và cung cấp thông tin của các service trong một hệ thống Microservice. Khi một service đăng ký thông tin với server, nó sẽ cung cấp các thông tin như host, port, trạng thái của nó. Và nó cũng thường xuyên gửi heartbeat message để thông báo tình trạng của mình cho server. Do đó, server này có thể dễ dàng cung cấp thông tin về các service khi chúng được gọi tới từ các service khác.
Đây chính là những điểm cơ bản về Eureka Server của Netflix OSS (Open Source Software) mà mình muốn đề cập trong bài viết này đó các bạn!
Trong bài viết này, mình sẽ hướng dẫn các bạn cách setup để có thể chạy một Eureka Server các bạn nhé!
Có 2 cách để chúng ta làm việc này: cách thứ nhất là sử dụng trực tiếp tập tin .war file từ Netflix và cách thứ hai là sử dụng Spring Cloud Netflix.
Cài đặt Eureka Server sử dụng tập tin .war của Netflix
Để có được tập tin cài đặt .war của Eureka Server từ Netflix, chúng ta có hai cách:
Cách đầu tiên là chúng ta sẽ build nó từ source code.
Toàn bộ source code của Eureka Netflix được open source trên Github tại đây. Các bạn hãy clone source code này về, sau đó sử dụng Gradle để build toàn bộ source code sử dụng câu lệnh:
1 |
./gradlew clean build |
Sau khi đã build xong thì các bạn có thể vào thư mục eureka-server/build/libs/ để lấy tập tin .war vừa mới build được. Của mình hiện tại thì tên tập tin là eureka-server-1.8.9-SNAPSHOT.war.
Cách thứ hai là mình sẽ download tập tin này trực tiếp từ các Remote Maven Repository như https://mvnrepository.com/artifact/com.netflix.eureka/eureka-server.
Hiện tại phiên bản mới nhất của Eureka Server là eureka-server-1.8.8.war.
Sau khi đã có tập tin .war của Eureka Server xong, chúng ta có thể sử dụng các Java Server Runtime như Apache Tomcat, Jetty để deploy nó lên.
Mình sẽ sử dụng Apache Tomcat trong bài viết này và build tập tin .war của Eureka Server từ source. Sau khi start Apache Tomcat xong, mình sẽ truy cập vào Eureka Server với địa chỉ như sau:
http://localhost:8080/eureka-server-1.8.9-SNAPSHOT/
Kết quả:
Trong phần “Instances currently registered with Eureka” sẽ chứa thông tin của tất cả các service đã đăng ký với Eureka Server này. Vì hiện tại chưa có service nào đăng ký nên các bạn sẽ không thấy gì ở đây cả.
Cài đặt Eureka Server sử dụng Spring Cloud Netflix
Sử dụng Spring Cloud Netflix làm cho việc cài đặt Eureka Server trở nên dễ dàng hơn. Các bạn chỉ cần tạo một Spring Boot project với Eureka Server dependency như sau:
Kết quả của mình như sau:
Sau đó, vào class main của ứng dụng Spring Boot của chúng ta, khai báo thêm một annotation tên là @EnableEurekaServer như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.huongdanjava.springcloud.eurekaserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class SpringCloudEurekaServerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaServerApplication.class, args); } } |
thì khi chạy kết quả sẽ là:
Nhìn vào hình ảnh trên, các bạn có thể thấy, thông tin hiển thị ở đây không khác gì nhiều so với khi chúng ta cài đặt Eureka Server sử dụng tập tin .war từ Netflix cả, phải không các bạn?
Nhưng có một số điểm mà các bạn cần lưu ý khi cài đặt Eureka Server bằng Spring Cloud Netflix như sau:
Port mặc định của Eureka Server là 8761 nhưng ở đây, nó đang sử dụng port mặc định của Tomcat là 8080.
Chúng ta nên cấu hình port cho giống với port mặc định của Eureka Server bằng cách thêm property server.port vào tập tin cấu hình của ứng dụng application.properties.
1 |
server.port=8761 |
Mặc định thì Eureka Server này cũng đóng vai trò như là một service trong một hệ thống Microservices.
Do đó, nó cũng đăng ký chính nó với Eureka Server và tìm thông tin của những service khác, nhưng mặc định địa chỉ Eureka Server mà nó đăng ký là http://localhost:8761/eureka. Bởi vì server này không tồn tại, do đó, nếu các bạn kiểm tra lại console, các bạn sẽ thấy lỗi sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
2018-04-21 22:16:04.642[0;39m [31mERROR[0;39m [35m2027[0;39m [2m---[0;39m [2m[nfoReplicator-0][0;39m [36mc.n.d.s.t.d.RedirectingEurekaHttpClient [0;39m [2m:[0;39m Request execution error com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused (Connection refused) at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:187) ~[jersey-apache-client4-1.19.1.jar:1.19.1] at com.sun.jersey.api.client.filter.GZIPContentEncodingFilter.handle(GZIPContentEncodingFilter.java:123) ~[jersey-client-1.19.1.jar:1.19.1] at com.netflix.discovery.EurekaIdentityHeaderFilter.handle(EurekaIdentityHeaderFilter.java:27) ~[eureka-client-1.8.7.jar:1.8.7] at com.sun.jersey.api.client.Client.handle(Client.java:652) ~[jersey-client-1.19.1.jar:1.19.1] at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682) ~[jersey-client-1.19.1.jar:1.19.1] at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) ~[jersey-client-1.19.1.jar:1.19.1] at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:570) ~[jersey-client-1.19.1.jar:1.19.1] at com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient.register(AbstractJerseyEurekaHttpClient.java:56) ~[eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.MetricsCollectingEurekaHttpClient.execute(MetricsCollectingEurekaHttpClient.java:73) ~[eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.executeOnNewServer(RedirectingEurekaHttpClient.java:118) ~[eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.execute(RedirectingEurekaHttpClient.java:79) ~[eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:120) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.DiscoveryClient.register(DiscoveryClient.java:829) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.InstanceInfoReplicator.run(InstanceInfoReplicator.java:121) [eureka-client-1.8.7.jar:1.8.7] at com.netflix.discovery.InstanceInfoReplicator$1.run(InstanceInfoReplicator.java:101) [eureka-client-1.8.7.jar:1.8.7] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_131] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_131] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_131] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_131] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131] |
Chúng ta có thể fix những lỗi này nhưng theo mình nghĩ là không cần thiết. Đã là Eureka Server thì chỉ nên có chức năng là nơi để cho những service khác đăng ký và quản lý thông tin của chúng mà thôi.
Các bạn có thể disable cấu hình mặc định này bằng cách thêm 2 properties sau vào tập tin cấu hình của ứng dụng application.properties.
1 2 |
eureka.client.register-with-eureka=false eureka.client.fetch-registry=false |
Khi đó, start lại ứng dụng, các bạn sẽ không thấy vấn đề gì cả.