请选择 进入手机版 | 继续访问电脑版

技术控

    今日:13| 主题:53518
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] Using the Netflix stack with Spring boot: Ribbon

[复制链接]
哆啦不能没有A梦 发表于 2016-10-19 08:21:41
464 12

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
Inmy last article I gave a basic introduction into the concepts of a service oriented architecture (SOA) and microservices. I also made a small example about a service registry and how Netflix is involved into microservices with tools like Eureka . However, the story was quite unfinished, since we only made it possible for microservices to register themselves on the registry, but the ones consuming the microservices have nothing to do with the service registry… yet.
  Meet Ribbon

   Ribbon is an interceptor that goes well with Eureka. It allows you to look up the hostname/IP of a service and does stuff like client-side load balancing for you as well. Now the only question is, what does Spring have to do with that? Well, if you followed my article about consuming a REST service , you should be familiar with  RestTemplate  already. When using the Eureka Discovery dependency, you can use the @LoadBalanced annotation to set up a RestTemplate using the Ribbon interceptor.
   

Using the Netflix stack with Spring boot: Ribbon

Using the Netflix stack with Spring boot: Ribbon

  Setting up our application

   In case you didn’t follow my article about Eureka, I suggest you download the code from GitHub . If you have both projects (the service registry and the service itself) imported in your IDE it’s time to create our next project, the consumer.
   Open the Spring Initializr , and add both the Web , Eureka Discovery , Thymeleaf and Actuator dependencies.
   

Using the Netflix stack with Spring boot: Ribbon

Using the Netflix stack with Spring boot: Ribbon

  Configuring Eureka

   The first step we’re going to configure is how to set up the Eureka discovery. First of all open application.properties (or application.yml ) and add the following properties:
  1. # application.properties
  2. eureka.client.healthcheck.enabled=true
  3. eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
  4. eureka.instance.statusPageUrlPath=/info
  5. eureka.instance.healthCheckUrlPath=/health
复制代码
  1. # application.yml
  2. eureka:
  3.   client:
  4.     healthcheck:
  5.       enabled: true
  6.     service-url:
  7.       default-zone: http://localhost:8761/eureka/
  8.   instance:
  9.     status-page-url-path: /info
  10.     health-check-url-path: /health
复制代码
This should look quite familiar, because this is the same configuration we applied to set up our service itself. The health check and status page URLs are provided by the actuator, so we don’t have to do anything for that (except adding the actuator as a dependency).
  We also have to give the application a name, since it will be used to register itself on Eureka with that name. Yes that’s right, the service registry is not only limited to services, but applications can register themself on Eureka as well.
   To give it a name we use the spring.application.name property:
  1. # application.properties
  2. spring.application.name=task-app
复制代码
Or in YAML:
  1. # application.yml
  2. spring:
  3.   application:
  4.     name: task-app
复制代码
  And finally, we also have to enable the Eureka discovery by adding the @EnableEurekaClient annotation to our main class like this:
  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. public class SpringBootEurekaConsumerApplication {
  4.     public static void main(String[] args) {
  5.         SpringApplication.run(SpringBootEurekaConsumerApplication.class, args);
  6.     }
  7. }
复制代码
Adding the DTO

  Now, because we will consume the task service we wrote earlier, we’ll have to use the same “format” as the API, so we’ll use the same DTO. To make it easier for myself I’ll just copy the code from the microservice itself.
  1. public class TaskDTO {
  2.     private Long id;
  3.     private String task;
  4.     private boolean completed;
  5.     public TaskDTO() {
  6.     }
  7.     public TaskDTO(String task, boolean completed) {
  8.         this(null, task, completed);
  9.     }
  10.     public TaskDTO(Long id, String task, boolean completed) {
  11.         this.id = id;
  12.         this.task = task;
  13.         this.completed = completed;
  14.     }
  15.     public Long getId() {
  16.         return id;
  17.     }
  18.     public String getTask() {
  19.         return task;
  20.     }
  21.     public void setTask(String task) {
  22.         this.task = task;
  23.     }
  24.     public boolean isCompleted() {
  25.         return completed;
  26.     }
  27.     public void setCompleted(boolean completed) {
  28.         this.completed = completed;
  29.     }
  30. }
复制代码
Creating the HTML

   Out of laziness I will recycle the HTML from an article I made earlier. Create a file called tasks.html inside the src/main/resources/templates folder with the following content:
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.   <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Raleway:400,300,600" />
  5.   <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/4.0.0/normalize.min.css" />
  6.   <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" />
  7.   <title>Task application</title>
  8. </head>
  9. <body>
  10.   <div class="container">
  11.     <h1>My tasks</h1>
  12.     <div th:each="task : ${tasks}">
  13.       <input type="checkbox" name="completed" th:checked="${task.completed}" disabled />
  14.       <span th:text="${task.task}"></span>
  15.     </div>
  16.   </div>
  17. </body>
  18. </html>
复制代码
  I’m using checkboxes here but disabled them because I didn’t implement the API calls yet to update tasks. Anyhow, I’m using Thymeleaf here as a template engine. However, the default settings are a bit strict, so open application.properties (or application.yml ) and set the following properties:
  1. # application.properties
  2. spring.thymeleaf.cache=false
  3. spring.thymeleaf.mode=LEGACYHTML5
复制代码
  1. # application.yml
  2. spring:
  3.   thymeleaf:
  4.     cache: false
  5.     mode: LEGACYHTML5
复制代码
  The LEGACYHTML5 mode allows you to write things like <br> without properly closing the elements. So if you didn’t use this mode, you would have to write <br /> . The same applies to attributes. In the HTML above I’ve disabled all checkboxes using the disabled property. Without LEGACYHTML5 you would have to write disabled="disabled" .
   However, choosing this mode requires you to add an additional dependency to your Maven descriptor called nekohtml :
  1. <dependency>
  2.     <groupId>net.sourceforge.nekohtml</groupId>
  3.     <artifactId>nekohtml</artifactId>
  4.     <version>1.9.22</version>
  5.     <scope>runtime</scope>
  6. </dependency>
复制代码
Calling the REST API

   Before we start writing our service, we have to set up a RestTemplate . If you used Spring cloud before, you might know that a RestTemplate was automatically created for you, however, since the Brixton release of Spring cloud, this is no longer true. When using Eureka Discovery, you’ll still have to create a RestTemplate .
  So let’s do that by opening the main class and creating a bean:
  1. # application.yml
  2. eureka:
  3.   client:
  4.     healthcheck:
  5.       enabled: true
  6.     service-url:
  7.       default-zone: http://localhost:8761/eureka/
  8.   instance:
  9.     status-page-url-path: /info
  10.     health-check-url-path: /health0
复制代码
  Now the next step is to create our service and autowire the RestTemplate :
  1. # application.yml
  2. eureka:
  3.   client:
  4.     healthcheck:
  5.       enabled: true
  6.     service-url:
  7.       default-zone: http://localhost:8761/eureka/
  8.   instance:
  9.     status-page-url-path: /info
  10.     health-check-url-path: /health1
复制代码
  Now, to use RestTemplate with generic types like List<TaskDTO> , you’ll have to use ParameterizedTypeReference . For our example it doesn’t really matter whether or not you use an array or a list, but for demonstration I’ll use ParameterizedTypeReference . To use it, create an anonymous inner class and extend from this class like this:
  1. # application.yml
  2. eureka:
  3.   client:
  4.     healthcheck:
  5.       enabled: true
  6.     service-url:
  7.       default-zone: http://localhost:8761/eureka/
  8.   instance:
  9.     status-page-url-path: /info
  10.     health-check-url-path: /health2
复制代码
  Now you can use it with RestTemplate like this:
  1. # application.yml
  2. eureka:
  3.   client:
  4.     healthcheck:
  5.       enabled: true
  6.     service-url:
  7.       default-zone: http://localhost:8761/eureka/
  8.   instance:
  9.     status-page-url-path: /info
  10.     health-check-url-path: /health3
复制代码
  As you can see, I’m not using a real URL reference here, but I’m using the task-service name to refer to the service that is registered on Eureka with this name. This makes it very easy since nobody really needs to know where the microservice is located except the service registry.
  Using the service

  Now, the final step is to create a new controller and use the service within it:
  1. # application.yml
  2. eureka:
  3.   client:
  4.     healthcheck:
  5.       enabled: true
  6.     service-url:
  7.       default-zone: http://localhost:8761/eureka/
  8.   instance:
  9.     status-page-url-path: /info
  10.     health-check-url-path: /health4
复制代码
  Now you can run the application, but make sure you run the registry and the service as well. Also make sure they all have a different port so they can be ran simultaneous. You can change the port by overriding the server.port property, or by setting the SERVER_PORT environment variable.
  Testing it out

   If you open your application (I hosted it on port 8082, so for me it’s http://localhost:8082 ), you’ll see our task service is successfully being called:
   

Using the Netflix stack with Spring boot: Ribbon

Using the Netflix stack with Spring boot: Ribbon

   Now, to see if load balancing works fine, you could run the task service twice, but again, make sure they run on a different port. If you run the service twice and go to the Eureka dashboard , both instances should be listed:
   

Using the Netflix stack with Spring boot: Ribbon

Using the Netflix stack with Spring boot: Ribbon

  Now to make sure it’s being load balanced, you could open up your service and add some logging. Now refresh the application a few times and you’ll see that the log appears on both instances, ideally around 50% of the time.
   

Using the Netflix stack with Spring boot: Ribbon

Using the Netflix stack with Spring boot: Ribbon

  For me both instances showed the log statements the same amount of times, which means the client side load balancing is doing a fine job. This also demonstrate how easily horizontal scaling became with Eureka. Run a few more instances of your service and that should be it.
  It also allows you to decouple your services even more. It doesn’t matter what port your microservice runs on, or where it runs, as long as both the application and the microservice look at the same service registry, it’s all OK.
     Achievement: Used the powers of Netflix

    If you’re seeing this, then it means you successfully managed to make it through this tutorial. As usual, the code can be found on GitHub .



上一篇:Android CardView的使用细节
下一篇:【译】前端是 ???? 而 JavaScript 是 ????
何鑫 发表于 2016-10-24 11:37:20
我就算是一只癞蛤蟆,我也决不娶母癞蛤蟆.
回复 支持 反对

使用道具 举报

神经范 发表于 2016-10-25 19:50:20
不要为那些不愿在你身上花费时间的人而浪费你的时间.
回复 支持 反对

使用道具 举报

春枫 发表于 2016-10-26 08:46:10
大声告诉我这是几楼?
回复 支持 反对

使用道具 举报

1065639161 发表于 2016-10-26 09:28:18
站位支持
回复 支持 反对

使用道具 举报

抢红包 发表于 2016-10-29 05:36:24
有空一起交流一下
回复 支持 反对

使用道具 举报

呜呜 发表于 2016-11-1 16:43:32
呜呜和小伙伴们都惊呆了
回复 支持 反对

使用道具 举报

liluo1991 发表于 2016-11-2 12:16:33
楼上的很有激情啊!
回复 支持 反对

使用道具 举报

帅美俊 发表于 2016-11-3 12:04:12
为潜心回复,本人决定暂时不和异性朋友接触,谢谢合作.
回复 支持 反对

使用道具 举报

兰晓娟 发表于 2016-11-16 01:09:10
撸过 可以么
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )

© 2001-2017 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表