SpirngCloud之Ribbon的服务调用及负载均衡

一 概念

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

LB,即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用。 负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA。 常见的负载均衡有软件Nginx,LVS,硬件 F5等。 相应的在中间件,例如:dubbo和SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。

Ribbon概述
是 Netflixfa 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中,
Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读
取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。
在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的
列表信息,并基于内置的负载均衡算法,请求服务

Ribbon的主要作用
(1)服务调用
基于Ribbon实现服务调用, 是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助
RestTemplate 最终进行调用
(2)负载均衡
当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址

二 Ribbon配置初步

  • 启动一中的eureka-server项目和producer-service项目,然后再改producer-service的端口,启动2个客户端

    • 修改producer-service的类

       1 @RestController
       2 @RequestMapping("/api/v1/product")
       3 public class ProductController {
       4  5  6  7     @Value("${server.port}")
       8     private String port;
       9 10     @Autowired
      11     private ProductService productService;
      12 13     /**
      14      * 获取所有商品列表
      15      * @return
      16      */
      17     @RequestMapping("list")
      18     public Object list(){
      19         return productService.listProduct();
      20     }
      21 22 23     /**
      24      * 根据id查找商品详情
      25      * @param id
      26      * @return
      27      */
      28     @RequestMapping("find")
      29     public Object findById(int id){
      30 31         Product product = productService.findById(id);
      32 33         Product result = new Product();
      34         BeanUtils.copyProperties(product,result);
      35         result.setName( result.getName() + " data from port="+port );
      36         return result;
      37     }
  • 创建order-serveice项目

    • pom.xml

      <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
              </dependency><dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
          </dependencies>

      注:在springcloud的新版本中提供的服务发现的jar中以及包含了Ribbon的依赖。所以这里不需要导入任何额外的坐标(spring-cloud-starter-netflix-ribbon)

    • 启动类

       1 @SpringBootApplication
       2 public class OrderServiceApplication {
       3  4     public static void main(String[] args) {
       5         SpringApplication.run(OrderServiceApplication.class, args);
       6     }
       7  8  9     @Bean
      10     @LoadBalanced
      11     public RestTemplate restTemplate() {
      12         return new RestTemplate();
      13     }
      14 15 16 }
    • Web层

      @RestController
      @RequestMapping("/api/v1/order")
      public class OrderController {
      ​
      ​
          @Autowired(required = false)
          private ProductOrderServiceImpl productOrderService;
      ​
      ​
          @RequestMapping("/save")
          public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){
      ​
              return productOrderService.save(userId, productId);
          }
      ​
      ​
      ​
      ​
      }
    • Service层

      @Service
      public class ProductOrderServiceImpl {
      ​
      ​
          @Autowired
          private RestTemplate restTemplate;
      ​
          public ProductOrder save(int userId, int productId) {
              System.out.println("123");
      ​
              Object obj = restTemplate.getForObject("http://product-service/api/v1/product/find?id="+productId, Object.class);
      ​
              System.out.println(obj);
      ​
              ProductOrder productOrder = new ProductOrder();
              productOrder.setCreateTime(new Date());
              productOrder.setUserId(userId);
              productOrder.setTradeNo(UUID.randomUUID().toString());
      ​
              return productOrder;
          }
      }
    • Bo类

      /**
       * 商品订单实体类
       */
      public class ProductOrder implements Serializable {
      ​
      ​
          private int id;
      ​
          /**
           * 商品名称
           */
          private String productName;
      ​
          /**
           * 订单号
           */
          private  String tradeNo;
      ​
          /**
           * 价格,分
           */
          private int price;
      ​
      ​
          private Date createTime;
      ​
      ​
          private int userId;
      ​
          private String userName;
      ​
      ​
          public int getUserId() {
              return userId;
          }
      ​
          public void setUserId(int userId) {
              this.userId = userId;
          }
      ​
          public String getUserName() {
              return userName;
          }
      ​
          public void setUserName(String userName) {
              this.userName = userName;
          }
      ​
          public int getId() {
              return id;
          }
      ​
          public void setId(int id) {
              this.id = id;
          }
      ​
          public String getProductName() {
              return productName;
          }
      ​
          public void setProductName(String productName) {
              this.productName = productName;
          }
      ​
          public String getTradeNo() {
              return tradeNo;
          }
      ​
          public void setTradeNo(String tradeNo) {
              this.tradeNo = tradeNo;
          }
      ​
          public int getPrice() {
              return price;
          }
      ​
          public void setPrice(int price) {
              this.price = price;
          }
      ​
          public Date getCreateTime() {
              return createTime;
          }
      ​
          public void setCreateTime(Date createTime) {
              this.createTime = createTime;
          }
      }
      ​
    • 配置文件

      server:
        port: 8781
      ​
      ​
      #指定注册中心地址
      eureka:
        client:
          serviceUrl:
            defaultZone: http://localhost:8761/eureka/
      ​
      #服务的名称
      spring:
        application:
          name: order-service
    • 结果:2个结果在轮询

{id=1, name=iphonex data from port=8772, price=9999, store=10}
{id=1, name=iphonex data from port=8771, price=9999, store=10}
{id=1, name=iphonex data from port=8772, price=9999, store=10}
{id=1, name=iphonex data from port=8771, price=9999, store=10}
{id=1, name=iphonex data from port=8772, price=9999, store=10}
{id=1, name=iphonex data from port=8771, price=9999, store=10}

 

如要修改它的负载均衡策略:

service-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
posted @ 2019-10-16 17:48  天宇轩-王  阅读(295)  评论(0编辑  收藏  举报