0%

SpringCloud-rest+ribbon

Ribbon简介

  • ribbon

    在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。在这一篇文章首先讲解下基于ribbon+rest;

    ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon.

Ribbon使用

  • 创建工程

    1.Cloud Discovery>>Eureka Discovery工程

    2.pom.xml中添加web依赖:

      <!--web-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
    
      <!--不写getter/setter的插件-->
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
      </dependency>
      
    

    3.启动类添加@EnableEurekaClient注解:

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

    4.application.yml配置文件配置服务注册地址:

      eureka:
        client:
          service-url:
            defaultZone: http://172.96.251.101:8761/eureka
      spring:
        application:
          name: service-Ribbon
                #service-restTemplate-Ribbon
      
      ##更改ribbon默认的负载均衡方式(默认是轮循,改为随机)
      ##WXPROJECT:目标应用的名称
      #WXPROJECT:
      #  ribbon:
      #    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
      
      server:
        port: 8084
        
    

    5.依然调用WXPROJECT这个服务的productInfo方法,所以创建实体类Product.java

        @Data
          public class Product {
          
              private String productId;
              private String productName;
              private BigDecimal productPrice;
              private Integer productStock;
              private String productDescription;
              private String productIcon;
              private String productStatus;
              private String categoryType;
              private Date createTime;
              private Date updateTime;    
          }
          
    

    6.创建RestTemplateConfig.java

      package com.ux.resttemplateribbon.restTemplateConfig;
    
      import org.springframework.cloud.client.loadbalancer.LoadBalanced;
      import org.springframework.context.annotation.Bean;
      import org.springframework.stereotype.Component;
      import org.springframework.web.client.RestTemplate;
      
      @Component
      public class RestTemplateConfig {
      
          @Bean
          @LoadBalanced
          public RestTemplate restTemplate() {
              return new RestTemplate();
          }
      }
      
    

    7.利用RestTeamlate+LoadBalanced注解实现对远程服务的调用:

      package com.ux.resttemplateribbon.controller;
    
      import com.ux.resttemplateribbon.pojo.Product;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.client.RestTemplate;
      
      /**
       * 利用RestTeamlate+LoadBalanced注解实现对远程服务的调用:
       * **************@Bean
       * **************@LoadBalanced public RestTemplate restTemplate() {
       * **************return new RestTemplate();
       * **************}
       * <p>
       * <p>
       * 本质依然是RestTeamlate+loadBalancerClient
       */
      
      @Slf4j
      @RestController
      @RequestMapping("/client/product")
      public class ProductController {
      
          @Autowired
          RestTemplate restTemplate;
      
          @GetMapping("/info")
          public Product info(@RequestParam("productId") String productId) {
      
              Product result = restTemplate.getForObject("http://WXPROJECT/product/productInfo?productId=" + productId, Product.class);
      
              log.info("~~~~~Product={}", result);
              return result;
          }
      }
    

小结

  • 小结

    利用RestTeamlate+LoadBalanced注解实现对远程服务的调用本质依然是RestTeamlate+loadBalancerClient,RestTeamlate+loadBalancerClient调用方式如下,不需要单独写RestTemplateConfig.java了:

      package com.ux.resttemplateribbon.controller;
    
      import com.ux.resttemplateribbon.pojo.Product;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.cloud.client.ServiceInstance;
      import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      import org.springframework.web.client.RestTemplate;
      
      /**
       * restTeamlate+loadBalancerClient(根据服务名称获取host和端口构造成url)实现服务之间的请求调用
       */
      
      @Slf4j
      @RestController
      @RequestMapping("/client/product")
      public class ProductController2 {
      
          @Autowired
          LoadBalancerClient loadBalancerClient;
      
          @GetMapping("/info2")
          public Product info(@RequestParam("productId") String productId) {
      
              RestTemplate restTemplate = new RestTemplate();
              //根据服务名称获取服务信息
              ServiceInstance instance = loadBalancerClient.choose("WXPROJECT");
              //获取服务端口
              Integer port = instance.getPort();
              //获取服务host
              String host = instance.getHost();
              //构造(拼接)url  形式为:http://192.168.1.102:8081/product/productInfo?productId=11
              String url = String.format("http://%s:%s", host, port + "/product/productInfo?productId=" + productId);
              Product result = restTemplate.getForObject(url, Product.class);
              //Product result = restTemplate.getForObject("http://WXPROJECT/product/productInfo?productId="+productId, Product.class);
              log.info("~~~~~Product={}", url);
              return result;
          }
      }