Ribbon也是netfix开源的负载均衡框架。而feign则是spring对Ribbon和hystrix进行了进一步的封装的组件。

1.Ribbon

单机实现:关于注册中心的搭建在上篇文章中进行了描述就不赘述了。准备两个相同的服务模块,再准备一个消费者模块。

服务者模块:
端口8001服务者 application.yml配置:

server:
  port: 8001
eureka:
  client:
    service-url:
      defaultZone: http://eureka-7001.com:7001/eureka
  instance:
    prefer-ip-address: true #在Eureka注册中心显示服务者的ip
spring:
  application:
    name: PRODUCER

端口8002 服务者 application.yml配置

server:
  port: 8002
spring:
  application:
    name: PRODUCER
eureka:
  client:
    service-url:
      defaultZone: http://eureka-7001.com:7001/eureka
  instance:
    prefer-ip-address: true #在Eureka注册中心显示服务者的ip

准备服务者的controller

@RestController
@RequestMapping("/producer")
public class ProducerController {

    @RequestMapping("/user/{id}")
    public User getUser(@PathVariable("id") Long id){
    //两个服务者的controller可以通过后面的字符串来进行区分。方便观查负载均衡的思想
        return new User(id, "shine on your crazydiamond");
    }
}

准备消费者模块
application.yml配置

server:
  port: 9002
eureka:
  client:
    registerWithEureka: false #不注册到Eureka,不在注册中心显示
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka-7001.com:7001/eureka

准备消费者模块的controller
通过消费者拿到服务者提供的服务。
在这需要通过ribbon的RestTemplate对象实现访问服务者的服务。
我们需要将RestTemplate交于spring容器托管,在springboot都是通过java类进行配置
代码如下

@Configuration //相当于一个独立的spring的xml配置文件
public class ConsumerConfig {
    /**
     * 该对象用于消费者通过注册中心访问服务
     * @return
     */
    @Bean //表示返回的对象是一个bean
    @LoadBalanced //Ribbon用于配置负载均衡
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
	//在传统调用中都是直接访问生产者的服务的地址,在ribbon中使用服务的名称进行访问
    private static final String URL_PREFIX = "http://PRODUCER";
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/user/{id}")
    public User getUser(@PathVariable("id") Long id){
    	//服务者提供的服务的地址
        String url = URL_PREFIX+"/producer/user/"+id;
        return restTemplate.getForObject(url, User.class);
    }
}

然后依次启动注册中心,服务者/消费者

feign负载均衡原理 feign负载均衡策略配置_服务器


发现注册了两个服务

然后通过访问消费者的地址进行服务的获取

feign负载均衡原理 feign负载均衡策略配置_User_02


feign负载均衡原理 feign负载均衡策略配置_feign负载均衡原理_03


分别访问了两个服务者的controller进行了服务的获取。

这就是简单的ribbon负载均衡的实现

ribbon提供了多种算法进行了负载均衡的实现

算法

描述

RoundRobinRule(默认)

简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。

AvailabilityFilteringRule

对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。注意:可以通过修改配置loadbalancer..connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的..ActiveConnectionsLimit属性进行配置。



WeightedResponseTimeRule

为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。

ZoneAvoidanceRule

以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。



BestAvailableRule

忽略哪些短路的服务器,并选择并发数较低的服务器。

RandomRule

随机选择一个可用的服务器。

可以通过配置进行算法的选择
简单实现

@Configuration
public class ConsumerConfig {
    /**
     * 设置 ribbon负载均衡的计算方法
     * @return
     */
    @Bean
    public IRule getRule(){
        return new RandomRule();
    }
}

2.Feign
feign对ribbon进行了封装,通过webservice式的方式实现获取服务,即提供一个公共接口,该接口会通过代理对象帮我们实现服务调用
具体实现步骤:
抽取一个服务者和消费者的公共接口模块
导入依赖:

<!--导入feign的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

代理接口
只需要打上FeignClient注解即可,在该接口中写服务者中要提供的服务。以及访问的地址。

@FeignClient(value = "PRODUCER")//name要与服务名称一致
@RequestMapping("/producer")//和生产者路径要一致
public interface UserClient {

    @RequestMapping("/user/{id}")
    User getUser(@PathVariable("id") Long id);
}

服务者最好实现该接口,使服务者和消费者保持一致。

@RestController
@RequestMapping("/producer")
//实现UserClient进行限制 生产者和消费者保持一致
public class ProducerController implements UserClient {

    @RequestMapping("/user/{id}")//RESTful风格
    public User getUser(@PathVariable("id")Long id){
        return new User(id, "close to the edge");
    }
}

在消费者模块导入feign的依赖

<!--导入feign的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

消费者的controller

@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private UserClient userClient;

    @RequestMapping("/user/{id}")
    public User getUser(@PathVariable("id") Long id){
        return userClient.getUser(id);//直接通过该接口的代理对象访问服务者提供的服务
    }
}

消费者的入口类

@SpringBootApplication
@EnableEurekaClient
//对代理接口所在的包进行扫描,才能在controller注入该对象
@EnableFeignClients(basePackages = "cn.itsource.springcloud.client")
public class FeignConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApplication.class);
    }
}

feign的实现思路将我们可能进行的重复的操作,例如使用ribbon时url的拼接等繁复的步骤封装了,简洁。