先说一下负载均衡:服务访问量忒大,一个服务器顶不住,服务器一崩那不凉了,怎么办——多用几个服务器,使单个服务器承受的访问量分散开,通过调度算法让他们都有休息的时间,就算有一个服务器凉了,至少还有其他的服务器顶上,不至于服务崩了。实现分散这些访问压力到不同服务器者就是负载也。

Ribbon和Feign都是实现负载均衡的组件,Feign的本质是Ribbon,基于Ribbon。

通过一个情景来说明他们的区别:微服务Service作为服务方提供操作展示数据的服务,做一个服务方的集群,以分散访问压力;微服务Client作为访问方,通过远程调用访问Service访问这些数据。

分析:Service作为服务方肯定有service层,没有controller、Client作为访问方只提供controller,不提供service,也就是说要实现Client的controller去调用Service的service。(下面例子没上dao的代码,这里主要展示Ribbon和Feign用法的区别)

Ribbon:

既然是远程调用(一个服务调另一个服务),就要有一个去做调用的任务的类:

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConfigBean {
    @Bean
    @LoadBalanced //配置 负载均衡实现RestTemplate
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

然后就可以在controller进行肆无忌惮的远程调用了,当然在调用过程中会通过一些服务调度算法来让Service进行轮流提供服务,默认的是轮询

import java.util.List;

@RestController
public class DeptConsumerController {

    //消费者不应该有service层
    //RestTemplate模板,供我们直接调用。要注册到bean中

    //提供多种边界访问远程http服务的方法,简单的Restful服务模板
    @Autowired
    private RestTemplate restTemplate;

    //这里的地址写成变量,通过服务名来访问
    private static final String Rest_URL_PREFIX = "http://SPRINGCLOUD" +
            "-PROVIDER-DEPT";

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return restTemplate.getForObject(Rest_URL_PREFIX + "/dept/get/" + id,
                Dept.class);
    }

}

到这里就完成了,通过看controller的代码我们发现这里是通过地址来直接调用另一个微服务的service的,在写法上与我们那种controller直接调service的方式有点不同,为了适应代码习惯和我们的规范,Feign的作用就体现出来了

Feign:

可以说Feign是基于Ribbon的,Ribbon的配置不变,只不过Feign在Ribbon的基础上做了一层封装,把远程调用给用户透明化了:在写代码时感觉不是在远程调用,而是正常地controller调service

Service的service层接口在原来基础上加一个注解 @FeignClient 

import java.util.List;

// @Service("service")
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")  //用Feign需要的注解
public interface DeptClientService {

    @GetMapping("/dept/get/{id}")
    Dept queryById(@PathVariable("id")Long id);

}

这时候Client的controller代码写法就完全和之前那种一个服务内controller调service一样了,感觉不到是在远程调用:

import java.util.List;

@RestController
public class DeptConsumerController {

    @Autowired
    private DeptClientService service;

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return this.service.queryById(id);
    }

}

观察对比代码可以发现Feign多出来的这层封装是把 原来地址这行代码:

feign dubbo 在k8s 区别_feign dubbo 在k8s 区别

通过注解放到了Service的service接口里,不让controller直接通过地址去调用远程接口,调用的过程交给了Feign,相当于在controller和service之间加了一层。

虽然用Feign在代码上写着会舒服,但毕竟多了一层,多少得影响点性能吧。具体用的时候还是根据具体情况去用。

作为一个小白我只能单从代码写法上去对比他们的区别,欢迎大佬从底层实现上分析一波。初学cloud,欢迎指正。