1.简介
- Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法。使用Ribbon的时候,只要服务提供者的名称相同,就自动形成了集群,并且有默认的负载均衡策略(轮询)。
- Feign是对Ribbon的封装,简化了服务的调用方式,即调用服务的时候,不再需要拼接需要传递的参数到访问地址上,而是采用定义接口(遵循Feign提供的模板)的方式去实现,Feign会完全代理HTTP请求。
2.使用
创建两个微服务,一个叫Consumer,一个叫Provider,用Consumer去调用Provider。当然,Eureka也是必不可少的。这三个微服务作为子模块,它们的父模块的pom.xml还是采用依赖版本管理的方式。
<properties>
<spring.cloud-version>Finchley.SR4</spring.cloud-version>
<spring.boot-version>2.0.5.RELEASE</spring.boot-version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.1.Ribbon
2.1.1.导入依赖
- 服务消费者Consumer:Eureka客户端、Ribbon场景启动器
<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>
<!-- Ribbon场景启动器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
- 服务提供者Provider:Eureka客户端(不需要Ribbon依赖)
<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>
</dependencies>
2.1.2.写启动类
- 服务消费者Consumer:配置RestTemplate、配置负载均衡策略
@SpringBootApplication
@EnableEurekaClient //可写可不写
public class RibbonConsumerApp {
public static void main(String[] args) {
SpringApplication.run(RibbonConsumerApp.class,args);
}
/**
* @LoadBalanced: 开启负载均衡策略,默认是轮询
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
/**
* 修改负载均衡策略(IRule是一个接口,只能new它的实现类)
* new RandomRule():随机策略
* new WeightedResponseTimeRule():权重策略
* new RoundRobinRule():轮询策略--默认
* @return
*/
@Bean
public IRule iRule(){
return new RoundRobinRule();
}
}
- 服务提供者Provider:正常写即可
@SpringBootApplication
@EnableEurekaClient //可写可不写
public class Provider8082App {
public static void main(String[] args) {
SpringApplication.run(Provider8082App.class,args);
}
}
2.1.3.写yml配置
- 服务消费者Consumer:配置端口和服务名称、注册服务到Eureka注册中心
server:
port: 9090
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
instance-id: ribbon-consumer:9090 #自定义一个服务id名称,否则就默认使用当前计算机名称作为服务的id
spring:
application:
name: RIBBON-CONSUMER #服务名称标识 如果不配置,则默认是UNKNOWN
- 服务提供者Provider:配置端口和服务名称、注册服务到Eureka注册中心
server:
port: 8082
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
instance-id: service-provider-ribbon:8082 #自定义一个服务id名称,否则就默认使用当前计算机名称作为服务的id
spring:
application:
name: SERVICE-PROVIDER-RIBBON #服务名称标识 如果不配置,则默认是UNKNOWN
2.1.4.写Controller
仅做一个简单的测试,在浏览器访问服务消费者,服务消费者调用服务提供者的服务,返回一个字符串在浏览器上展示
- 服务消费者Consumer:用RestTemplate来发HTTP请求,调用Provider
@RestController
public class RibbonConsumerController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/ribbon/consumer")
public String consumer(){
System.out.println("consumer...................");
//发送get请求,访问另一个provider服务
//如果需要传递参数,需要拼接到URL上
String s = restTemplate.getForObject("http://SERVICE-PROVIDER-RIBBON/ribbon/provider", String.class);
return s;
}
}
- 服务提供者Provider:返回一个字符串
@RestController
public class ProviderController8082 {
/**
* @return
*/
@GetMapping("/ribbon/provider")
public String provider(){
System.out.println("provider..............");
return "*****8082*****";
}
}
2.1.5.浏览器访问测试
2.2.Feign
Ribbon和Feign都是配置在服务消费者上,服务提供者的配置是一样的
2.2.1.导入依赖
- 服务消费者Consumer:Eureka客户端、Feign场景启动器(注意:依赖的名字叫openfeign)
<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>
<!-- feign场景启动器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
2.2.2.写启动类
- 服务消费者Consumer:
注意:一定要加@EnableFeignClients注解
/**
* @EnableFeignClients 这个注解表示开启动态代理
* 会自动递归扫描当前启动类所在的包【扫描所有添加了@FeignClient注解的接口,然后采用动态代理技术生成实现类,
* 创建对象保存到Spring容器中】
*/
@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class FeignConsumerApp {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApp.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
2.2.3.写yml配置
- 服务消费者Consumer:端口和服务名称配置、服务注册到Eureka服务中心
server:
port: 9091
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
instance-id: feign-consumer:9091 #自定义一个服务id名称,否则就默认使用当前计算机名称作为服务的id
spring:
application:
name: FEIGN-CONSUMER #服务名称标识 如果不配置,则默认是UNKNOWN
2.2.4.写Feign客户端接口
Feign客户端接口写在服务消费者方,它是一个接口,接口上需要添加@FeignClient注解。
接口中的方法参数、返回值、请求地址必须和对应的服务提供者Controller中的方法定义的一致。
为方便起见,可以直接把服务提供者中对应的方法copy过来,删除方法体即可。
/**
* @FeignClient 表明当前接口是Feign的客户端接口,并在value属性中指定所调用的服务名称
*/
@FeignClient(value = "SERVICE-PROVIDER")
@Component
public interface ProviderClient {
@GetMapping("/feign/provider")
String provider();
}
2.2.5.写Controller
- 服务消费者Consumer:依赖注入Client对象,调用方法即可(使用方式类似于mapper层接口)
@RestController
public class FeignConsumerController {
@Autowired
private ProviderClient providerClient;
@GetMapping("/feign/consumer")
public String feignConsumer(){
System.out.println("feignConsumer.....................");
String s = providerClient.provider();
return s;
}
}
2.2.6.浏览器访问测试
3.Ribbon和Feign的区别
Feign是通过定义FeignClient接口的方式调用(类似于mapper层接口的使用方式),我们只需要定义好接口,在接口上加@FeignClient注解并指定要调用的服务名称或者服务集群名称,在启动类上加@EnableFeignClients注解,Feign底层就会动态代理生成FeignClient接口的实现类,实现类中重写接口的方法,内部还是采用的Ribbon的方式去调用(用RestTemplate发送HTTP请求)。
由于Feign是对Ribbon进行的封装,所以Feign也有Ribbon的负载均衡。
另外,Feign内部也集成了Hystrix,所以我们一般会使用Feign。
4.总结
简单理解,Ribbon是SpringCloud中微服务之间的调用方式,有了它,我们可以通过微服务的名称去调用对应的微服务,如果多个微服务有相同的名称,就自动形成了集群,并且Ribbon会自动对集群进行负载均衡,默认的策略是轮询,也可以自己定义负载均衡策略。
Feign是对Ribbon进行的封装,拥有Ribbon的所有功能,优化的地方在于采用了定义FeignClient接口的方式去调用微服务,发送HTTP请求的步骤封装到了底层自动实现,使用更方便。