4、Spring Cloud-负载均衡 Ribbon

4.1、RestTemplate 简介

RestTemplate是Spring Resources中一个访问RESTful API 接口的网络请求框架。
 
RestTemplate 的设计 则和其他 Spring Template (例如 JdbcTemplate JmsTemplate )类似,都
是为执行复杂任务提供了一个具有默认行为的简单方法。
 
RestTemplate 是用来消费 REST 服务的,所以 RestTemplate 主要方法都与REST的HTTp
协议的一些方法紧密相连,例如 HEAD 、GET 、POST 、PUT、DELETE和OPTIONS 等方法
这些方法在 RestTemplate 类对应的方法为 headForHeaders()、getForObject()、 
postForObject()、put()和 delete () 等。
 
RestTemplate 支持常见的 Http 协议的请求方法,例如 Post、 Put、 Delete ,所以用
RestTemplate 很容易构建 RESTful API 。

 

4.2、Ribbon 简介

负载均衡是指将负载分摊到多个执行单元上,常见的负载均衡有两种方式。
 
1.独立进程单元,通过负载均衡策略,将请求转发到不同的执行单元上,例如 Ngnix 。
2.将负载均衡逻辑以代码的形式封装到服务消费者的客户端上,服务消费者客户端维护了一份服务提
  供者的信息列 ,有了信息列表,通过负载均衡策略将请求分摊给多个服务提供者,从而达到负
  载均衡的目的。
 
Ribbon是Netflix 公司开源的一个负载均衡的组件,它属于上述的第2种方式
是将负载均衡逻辑封装在客户端中,并且运行在客户端的进程里
 
Ribbon是一个经过了云端测试的 IPC库,可以很好地控制 HTTP和TCP 客户端的负载均衡行为。
 
Spring Cloud 构建的微服务系统中, Ribbon 作为服务消费者的负载均衡器
两种使用方式:  
1、 和RestTemplate 相结合
2、是和 Feign 相结合。(Feign 已经默认集成了 Ribbon) 
 
Ribbon 有很多子模块,但很多模块没有用于生产环境,目前 Netflix 公司用于生产环境的 Ribbon
子模块如下:

 

 4.3、使用RestTemplate和Ribbon来消费

 

之前的案例中已经有了注册中心此时不在进行注册中心的代码实现
(之前关于Eureka的高可用中有两个端口的Eureka)
 
服务提供者的开发如下:
eureka-client地址:https://www.cnblogs.com/Mrchengs/p/10645860.html
是之前的工程进行改变的

 

ProviderService.java

package com.cr.eurekaclient.service;
import org.springframework.stereotype.Service;

@Service
public class ProviderService {

    public String  port(){
        return "8080";
    }
}

 

 PortController.java

package com.cr.eurekaclient.controller;

import com.cr.eurekaclient.service.ProviderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PortController {

    @Autowired
    ProviderService providerService;

    @GetMapping("/port")
    public String getPort(){
        return providerService.port();
    }
}

 

 配置文件:

server.port=8089
spring.application.name=CLINET
#应用起名字spring.application.name=provider
#注册服务时使用服务的ip地址
eureka.instance.prefer-ip-address=true
#服务中心地址
eureka.client.service-url.defaultZone=http://localhost:8762/eureka/

 访问:

 

去注册中心可以看到此时的服务已经在注册中心注册:

这里的Application将会是消费者中引用的地址!!!

 

 服务的消费者:

 

RibbonConfig.java

@Configuration
public class RibbonConfig {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

 

RibbonController.java

@RestController
public class RibbonController {
    @Autowired
    RibbonService ribbonService;

    @GetMapping("/port")
    public String port(){
        return ribbonService.port();
    }
}

 

RibbonService.java
@Service
public class RibbonService {

    @Autowired
    RestTemplate restTemplate;

    public  String port(){
        return restTemplate.getForObject("http://CLINET/port",String.class);
    }
}

 http://CLINET/port中的CLIENT为注册中心中的Application中的值

 

EurekaRibbonClientApplication.java
@EnableEurekaClient
@SpringBootApplication
public class EurekaRibbonClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaRibbonClientApplication.class, args);
    }
}

 

配置文件:

spring.application.name=eureka-ribbon-client
server.port=8088
eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
访问:localhost:8080之后、
看注册中心:

 

@LoadBalanced开启负载均衡功能 

测试实现: 

同时也将8090换成8089,使用maven进行打包

 

在cmd中运行两个项目:

 

 

 此时8089、8090端口都可以进行访问

 

 

 http://localhost:8088/port页面进行刷新请求

 

 

 

此似乎可以看到两个端口的服务都可以访问到!!
 
负载均衡器会轮流地请求CLIENT的两个实例中的“/port”请求

 

 4.4、loadBalancerClient 简介

负载均衡器的核 类为 LoadBalancerClient
LoadBalancerCiient 可以获取负载均衡的服务提供者的实例信息

 

在工程中进行测试:

 

RibbonController.java 

package com.cr.eurekaribbonclient.controller;

import com.cr.eurekaribbonclient.service.RibbonService;
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.RestController;

@RestController
public class RibbonController {
    @Autowired
    RibbonService ribbonService;

    @GetMapping("/port")
    public String port(){
        return ribbonService.port();
    }

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @GetMapping("/testRibbon")
    public String testRibbon(){
        ServiceInstance instance = loadBalancerClient.choose("CLINET");
        return instance.getHost()+ ":" + instance.getPort();
    }
}

 

继续运行项目:

 

 

LoadBalancerClient的choose("CLINET")方法可以轮流得到 eureka-client 的两个服务实例的信息
 
负载均衡LoadBalancerClient是从Eureka Client 获取服务注册列表信息的,并且将注册信息缓存一份
 
LoadBalancerCJient 调用 choose()方法时,根据负载均衡策略选择一个服务实例的信息,
从而进行了负载均衡
 
LoadBalancerClient 也可以不从 Eureka Client 获取注册列表信息,
这时需要自己维护 份服务注册列 信息
 
有两个不同 Uri 地址 (例如 example.com,google.com )的服务实例 ,通
stores.ribbon.listOfServers 来配 这些服务实例的 Uri
spring.application.name=eureka-ribbon-client
server.port=8088
eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
stores.ribbon.listOfServers:example.com,google.com
ribbon.eureka.enabled=false

 

 

package com.cr.eurekaribbonclient.controller;

import com.cr.eurekaribbonclient.service.RibbonService;
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.RestController;

@RestController
public class RibbonController {
    @Autowired
    RibbonService ribbonService;

    @GetMapping("/port")
    public String port(){
        return ribbonService.port();
    }

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @GetMapping("/testRibbon")
    public String testRibbon(){
        ServiceInstance instance = loadBalancerClient.choose("CLINET");
        return instance.getHost()+ ":" + instance.getPort();
    }

    //进一步说明
    @GetMapping("/hi")
    public String hi(){
        ServiceInstance instance = loadBalancerClient.choose("stores");
        return instance.getHost()+ ":" + instance.getPort();
    }
}
测试:

 

 

 

 后期会对源码进行相关的分析!!!
 
 
posted @ 2019-04-02 22:46  MrChengs  阅读(214)  评论(0编辑  收藏  举报