Pengenalan kepada Spring Cloud Netflix - Eureka

1. Gambaran keseluruhan

Dalam tutorial ini, kami akan memperkenalkan penemuan perkhidmatan di sisi pelanggan melalui " Spring Cloud Netflix Eureka ".

Penemuan perkhidmatan di sisi pelanggan membolehkan perkhidmatan mencari dan berkomunikasi antara satu sama lain tanpa nama host dan port yang dikodkan keras. Satu-satunya 'titik tetap' dalam seni bina seperti itu terdiri daripada pendaftaran perkhidmatan di mana setiap perkhidmatan harus mendaftar.

Kelemahannya ialah semua pelanggan mesti menerapkan logik tertentu untuk berinteraksi dengan titik tetap ini. Ini memerlukan perjalanan pulang pergi tambahan sebelum permintaan sebenar.

Dengan Netflix Eureka setiap pelanggan boleh bertindak sebagai pelayan secara serentak, untuk mereplikasi statusnya kepada rakan sebaya yang terhubung. Dengan kata lain, pelanggan mengambil senarai semua rakan sebaya dari pendaftaran perkhidmatan dan membuat semua permintaan selanjutnya ke perkhidmatan lain melalui algoritma pengimbang beban.

Untuk dimaklumkan mengenai kehadiran pelanggan, mereka harus menghantar isyarat degupan jantung ke pendaftaran.

Untuk mencapai matlamat penulisan ini, kami akan melaksanakan tiga perkhidmatan mikro :

  • yang pendaftaran perkhidmatan ( Eureka Server ),
  • perkhidmatan REST yang mendaftarkan dirinya di pendaftaran ( Eureka Client ) dan
  • aplikasi web, yang menggunakan perkhidmatan REST sebagai pelanggan yang mengetahui pendaftaran ( Spring Cloud Netflix Feign Client ).

2. Pelayan Eureka

Melaksanakan Eureka Server untuk pendaftaran perkhidmatan semudah:

  1. menambah pelayan spring-cloud-starter-netflix-eureka ke pergantungan
  2. aktifkan Eureka Server dalam @SpringBootApplication dengan memberi penjelasan dengan @EnableEurekaServer
  3. konfigurasikan beberapa sifat

Tetapi kita akan melakukannya selangkah demi selangkah.

Pertama kita akan membuat projek Maven baru dan memasukkan kebergantungan ke dalamnya. Anda harus perhatikan bahawa kami mengimport spring-cloud-starter-parent ke semua projek yang dijelaskan dalam tutorial ini:

 org.springframework.cloud spring-cloud-starter-netflix-eureka-server     org.springframework.cloud spring-cloud-starter-parent Greenwich.RELEASE pom import   

Nota: kami dapat menyemak siaran Spring Cloud terbaru dalam dokumentasi Spring's Projects.

Seterusnya, kami membuat kelas aplikasi utama:

@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }

Akhirnya, kami mengkonfigurasi sifat dalam format YAML ; jadi sebuah aplikasi.yml akan menjadi fail konfigurasi kami:

server: port: 8761 eureka: client: registerWithEureka: false fetchRegistry: false

Di sini kita mengkonfigurasi port aplikasi - 8761 adalah port lalai untuk pelayan Eureka . Kami memberitahu Pelanggan Eureka yang terpasang untuk tidak mendaftar dengan 'dirinya sendiri' kerana aplikasi kami harus bertindak sebagai pelayan.

Sekarang kita akan mengarahkan penyemak imbas kita ke // localhost: 8761 untuk melihat papan pemuka Eureka , di mana kita kemudian akan memeriksa keadaan yang didaftarkan.

Pada masa ini, kami melihat petunjuk asas seperti petunjuk status dan kesihatan.

3. Pelanggan Eureka

Agar @SpringBootApplication sedar-sedar, kami perlu memasukkan beberapa Spring Discovery Client (contohnya spring-cloud-starter-netflix-eureka-client ) ke dalam classpath kami .

Oleh itu, kita perlu memberi anotasi @Configuration dengan @EnableDiscoveryClient atau @EnableEurekaClient - perhatikan bahawa anotasi ini adalah pilihan jika kita mempunyai pergantungan spring-cloud-starter-netflix-eureka-client pada classpath.

Yang terakhir ini memberitahu Spring Boot untuk menggunakan Spring Netflix Eureka untuk penemuan perkhidmatan secara eksplisit. Untuk mengisi aplikasi pelanggan kami dengan beberapa contoh masa pakai , kami juga akan memasukkan pakej spring-boot-starter-web di pom.xml dan menerapkan pengawal REST .

Tetapi pertama, kami akan menambahkan pergantungan. Sekali lagi, kita boleh menyerahkannya kepada pergantungan musim bunga-awan-starter-induk untuk mengetahui versi artifak untuk kita:

 org.springframework.cloud spring-cloud-starter-netflix-eureka-starter   org.springframework.boot spring-boot-starter-web 

Di sini kita akan melaksanakan kelas aplikasi utama:

@SpringBootApplication @RestController public class EurekaClientApplication implements GreetingController { @Autowired @Lazy private EurekaClient eurekaClient; @Value("${spring.application.name}") private String appName; public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } @Override public String greeting() { return String.format( "Hello from '%s'!", eurekaClient.getApplication(appName).getName()); } }

Dan antara muka GreetingController :

public interface GreetingController { @RequestMapping("/greeting") String greeting(); }

Di sini, bukannya antara muka, kita juga boleh menyatakan pemetaan di dalam kelas EurekaClientApplication . Antaramuka boleh berguna jika kita ingin membaginya antara pelayan dan pelanggan.

Seterusnya, kita harus menyiapkan application.yml dengan nama aplikasi Spring yang dikonfigurasi untuk mengenal pasti pelanggan kita secara unik dalam senarai aplikasi yang didaftarkan.

Kami boleh membiarkan Spring Boot memilih port rawak untuk kami kerana kemudian kami mengakses perkhidmatan ini dengan namanya.

Akhirnya, kami harus memberitahu pelanggan kami, di mana ia harus mencari pendaftaran:

spring: application: name: spring-cloud-eureka-client server: port: 0 eureka: client: serviceUrl: defaultZone: ${EUREKA_URI://localhost:8761/eureka} instance: preferIpAddress: true

Ketika kami memutuskan untuk menubuhkan Pelanggan Eureka dengan cara ini, kami ingat bahawa perkhidmatan seperti ini kemudiannya mudah ditingkatkan.

Sekarang kita akan menjalankan klien dan mengarahkan penyemak imbas kita ke // localhost: 8761 sekali lagi, untuk melihat status pendaftarannya di Eureka Dashboard. Dengan menggunakan Dashboard, kita dapat melakukan konfigurasi lebih lanjut misalnya menghubungkan halaman utama klien yang berdaftar dengan Dashboard untuk tujuan pentadbiran. Walau bagaimanapun, pilihan konfigurasi berada di luar ruang lingkup artikel ini.

4. Pelanggan Feign

Untuk menyelesaikan projek kami dengan tiga perkhidmatan mikro yang bergantung, kami kini akan melaksanakan aplikasi web yang menggunakan REST menggunakan Spring Netflix Feign Client .

Think of Feign as discovery-aware SpringRestTemplate using interfaces to communicate with endpoints. This interfaces will be automatically implemented at runtime and instead of service-urls, it is using service-names.

Without Feign we would have to autowire an instance of EurekaClient into our controller with which we could receive a service-information by service-name as an Application object.

We would use this Application to get a list of all instances of this service, pick a suitable one and use this InstanceInfo to get hostname and port. With this, we could do a standard request with any http client.

For example:

@Autowired private EurekaClient eurekaClient; public void doRequest() { Application application = eurekaClient.getApplication("spring-cloud-eureka-client"); InstanceInfo instanceInfo = application.getInstances().get(0); String hostname = instanceInfo.getHostName(); int port = instanceInfo.getPort(); // ... }

A RestTemplate can also be used to access Eureka client-services by name, but this topic is beyond this write-up.

To set up our Feign Client project, we're going to add the following four dependencies to its pom.xml:

 org.springframework.cloud spring-cloud-starter-feign   org.springframework.cloud spring-cloud-starter-netflix-eureka-client   org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-thymeleaf 

The Feign Client is located in the spring-cloud-starter-feign package. To enable it, we have to annotate a @Configuration with @EnableFeignClients. To use it, we simply annotate an interface with @FeignClient(“service-name”) and auto-wire it into a controller.

A good method to create such FeignClients is to create interfaces with @RequestMapping annotated methods and put them into a separate module. This way they can be shared between server and client. On server-side, you can implement them as @Controller, and on client-side, they can be extended and annotated as @FeignClient.

Furthermore, the spring-cloud-starter-eureka package needs to be included in the project and enabled by annotating the main application class with @EnableEurekaClient.

The spring-boot-starter-web and spring-boot-starter-thymeleaf dependencies are used to present a view, containing fetched data from our REST service.

This will be our Feign Client interface:

@FeignClient("spring-cloud-eureka-client") public interface GreetingClient { @RequestMapping("/greeting") String greeting(); }

Here we will implement the main application class which simultaneously acts as a controller:

@SpringBootApplication @EnableFeignClients @Controller public class FeignClientApplication { @Autowired private GreetingClient greetingClient; public static void main(String[] args) { SpringApplication.run(FeignClientApplication.class, args); } @RequestMapping("/get-greeting") public String greeting(Model model) { model.addAttribute("greeting", greetingClient.greeting()); return "greeting-view"; } } 

This will be the HTML template for our view:

   Greeting Page   

At least the application.yml configuration file is almost the same as in the previous step:

spring: application: name: spring-cloud-eureka-feign-client server: port: 8080 eureka: client: serviceUrl: defaultZone: ${EUREKA_URI://localhost:8761/eureka}

Now we can build and run this service. Finally, we'll point our browser to //localhost:8080/get-greeting and it should display something like the following:

Hello from SPRING-CLOUD-EUREKA-CLIENT!

5. ‘TransportException: Cannot Execute Request on Any Known Server'

While running Eureka server we often run into exceptions like:

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

Basically, this happens due to the wrong configuration in application.properties or application.yml. Eureka provides two properties for the client that can be configurable.

  • registerWithEureka: If we make this property as true then while the server starts the inbuilt client will try to register itself with the Eureka server.
  • fetchRegistry: The inbuilt client will try to fetch the Eureka registry if we configure this property as true.

Now when we start up the Eureka server, we don't want to register the inbuilt client to configure itself with the server.

If we mark the above properties as true (or don't configure them as they're true by default) while starting the server, the inbuilt client tries to register itself with the Eureka server and also tries to fetch registry which is not yet available. As a result, we get TransportException.

So we should never configure these properties as true in the Eureka server applications. The correct settings that should be put in application.yml are given below:

eureka: client: registerWithEureka: false fetchRegistry: false

6. Conclusion

As we've seen, we're now able to implement a service registry using Spring Netflix Eureka Server and register some Eureka Clients with it.

Because our Eureka Client from step 3 listens on a randomly chosen port, it doesn't know its location without the information from the registry. With a Feign Client and our registry, we can locate and consume the REST service, even when the location changes.

Akhirnya, kami mendapat gambaran besar mengenai penggunaan penemuan perkhidmatan dalam seni bina perkhidmatan mikro.

Seperti biasa, anda akan menemui sumber-sumber di GitHub, yang juga merangkumi sekumpulan fail yang berkaitan dengan Docker untuk digunakan dengan komposisi docker untuk membuat kontena dari projek kami.