SpringCloud初级学习(五)------Feign负载均衡
前言
Feign是一个声明式WebService客户端,使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。
简单来说,在之前使用Ribbon的时候,我们调用微服务还是通过HttpTemplate来调用的,虽然我们的调用方式从最初的url变成了服务名.
但是我们目前开发中,使用最多的还是面向接口编程,比如我们的service层,一般都会有service接口,然后实现类.为了使调用微服务也变成面向接口的方式,Feign由此而生.
正文
1. Feign能干什么?
前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。
Feign集成了Ribbon,利用Ribbon维护了服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用
2. 抽象出微服务的接口到公共api层
既然Feign可以让我们调用微服务由RestTemplate变成面向接口的方式,自然而然我们需要有接口,而接口是给所有的服务调用者来使用的,因此我们将其放在helloword-cloud-api
中.
-
首先在
helloword-cloud-api
工程的pom文件中加入Feign的依赖:<!--Feign依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
-
在api工程中新建
service
包,创建基于服务提供者的接口DeptClient
:@FeignClient(value = "HELLOWORD-CLOUD-PROVIDER") public interface DeptClient { /** * 获取部门信息 * @param id * @return */ @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(); }
@FeignClient注解表明该接口是基于Feign的服务客户端,服务调用者可以直接通过该客户端来调用微服务,不需要再使用
RestTemplate
来调用;注解中的value
属性指定该客户端调用的微服务是哪一个. -
该接口中方法上的
@RequestMapping
注解,指定了在调用该方法的时候,映射到服务提供者的接口路由. -
在使用的时候,我们只需要调用该客户端对应的方法,Feign会自动根据方法上的请求路径,找到对应微服务的接口来获取信息.
-
最后还需要将api模块重新打包安装.
3. 使用Feign来实现服务调用
在前面我们已经构建好了基于Feign的微服务客户端,要使用该客户端,我们要新建一个服务消费者来调用.
我们新建一个工程helloword-cloud-consumer-feign
,该工程不会使用RestTemplate
来调用微服务.
-
新建子模块
helloword-cloud-consumer-feign
,pom文件如下:<?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>helloword-cloud</artifactId> <groupId>com.xiaojian.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <packaging>jar</packaging> <artifactId>helloword-cloud-consumer-feign</artifactId> <dependencies> <dependency> <groupId>com.xiaojian.springcloud</groupId> <artifactId>helloword-cloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <!--Ribbon相关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <!--增加feign支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> </dependencies> </project>
需要注意的是,这个pom文件中依赖的组件和
helloword-cloud-consumer
工程是差不多的,只不过多了一个对Feign的依赖:<!--增加feign支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
-
在主启动类上添加注解
@EnableFeignClients
和@ComponentScan
,来扫描我们api模块中新建的接口:@SpringBootApplication @EnableEurekaClient //@RibbonClient(name = "HELLOWORD-CLOUD-PROVIDER", configuration = MyRule.class) @EnableFeignClients(basePackages = {"com.xiaojian.cloud"}) @ComponentScan("com.xiaojian.cloud") public class DeptConsumerFeign80 { public static void main(String[] args) { SpringApplication.run(DeptConsumerFeign80.class, args); } }
由于Feign内部集成了Ribbon,这里可以不用
@RibbonClient
注解 -
该工程的配置文件也要配置eureka,注册到注册中心,去获取服务列表:
server: port: 80 eureka: client: register-with-eureka: false #false表示不向注册中心注册自己 service-url: defaultZone: http://localhost:7001/eureka/ #设置与eureka server交互的地址
-
新建controller,在controller中注入Feign的客户端:
@RestController public class DeptControllerConsumer { @Autowired private DeptClient deptClient; @RequestMapping("/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return deptClient.get(id); } @RequestMapping("/consumer/dept/list") public List<Dept> list() { return deptClient.list(); } }
-
启动所有的服务(包括eureka,服务提供者和服务消费者),在浏览器访问
http://localhost/consumer/dept/get/1
或者其他的接口地址,我们可以看到,数据可以正常拿到了!!!而且在访问的时候,我们可以看到数据的来源也是随着调用的次数而改变的,这说明Feign也对我们的请求做了负载均衡.
总结
在本篇博文中,我们简单了解了Feign在微服务架构中的使用方式,在使用Feign之前,我们使用RestTemplate
的方式通过服务名,显示的调用微服务;而使用了Feign之后,我们可以更加舒适的使用面向接口编程的方式来调用微服务,而且在Feign中,也使用了Ribbon的负载均衡,可以针对不同的服务分配不同的流量.
在下一篇博文中,我们将接触springcloud的另一款产品Hystrix
,它为我们的微服务提供了熔断、限流、降级等多种容灾方案,使我们的微服务更加稳定.