Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。
主要模块:producer(生产者)、consumer(消费者)。消费者调用生产者。Feign主要作用于服务层。
1.引入openfeign实现发送请求
我们在消费者的pom文件中引入openfeign。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
再加入loadbalance后变成:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>s-cloud-alibaba</artifactId> <groupId>site.longkui</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>consumer-1</artifactId> <dependencies> <!--spring boot web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--nacos服务发现--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </exclusion> </exclusions> </dependency> <!--openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- loadbalancer负载均衡 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> </dependencies> </project>
如果引入依赖失败,可以尝试重启IDEA,或者清除缓存重启,刷新maven等操作来解决。
然后在消费者的启动类上加入@EnableFeignClients注解。
然后,我们在消费者模块,创建server层。
package site.longkui.service; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient("service-producer") public interface ConsumerFeignService { @GetMapping("/user/getUser") String feignGetUser(); }
然后我们在消费者的controller层增加访问service层的代码
package site.longkui.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import site.longkui.service.ConsumerFeignService; @RestController @RequestMapping("/consumer") public class ConsumerController { @Autowired private RestTemplate restTemplate; @Autowired private ConsumerFeignService consumerFeignService; //消费者接口 @GetMapping("/getUser") public String getUser(){ //指出服务地址 String url="http://localhost:8010/user/getUser"; //返回值类型和我们的业务返回值一致 return restTemplate.getForObject(url, String.class); } //使用feign的消费者接口 @GetMapping("/testFeign") public String testFeign(){ return consumerFeignService.feignGetUser(); } }
我们访问消费者的新的接口地址:localhost:9010/consumer/testFeign
可以看到我们使用feign的方式访问到了生产者的接口。
2.feign实现负载均衡
为了测试负载均衡,我们新创建一个生产者,端口为8020。
我们复制一份生产者代码,把端口改成8020。然后启动这个服务。
我们也要修改生产者2的代码来区分一下内容:
注意:这只是为了显示是否负载均衡,实际生产中不会这样复制很多份代码。
然后我们访问消费者的代码。
可以看到,我们实现了负载均衡。
3.后记
实践中,发现如果不引入spring-cloud-starter-loadbalancer 会直接报错
Caused by: java.lang.IllegalStateException: No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?