Feign提供声明式的远程调用,借用动态代理实现远程调用,使编写Web服务客户端变得更容易。 Spring Cloud增加了对Spring MVC注释的支持,并使用了Spring Web中默认使用的相同HttpMessageConverters。 Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供负载均衡的http客户端。
快速入门
- Eureka-server配置
server.port=8088
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.security.user.name=mask
spring.security.user.password=111111
- Eureka-Server
@SpringBootApplication
@EnableEurekaServer
public class EurekaApp{
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class,args);
}
}
- 服务提供者A
spring.application.name=USER-SERVICE
eureka.instance.instance-id=001
eureka.instance.prefer-ip-address=true
eureka.instance.lease-expiration-duration-in-seconds=20
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.client.register-with-eureka=true
eureka.client.healthcheck.enabled=true
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://mask:111111@localhost:8088/eureka/
@SpringBootApplication
@EnableEurekaClient
@RestController
@RequestMapping("main")
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class,args);
}
@RequestMapping(value = "index", method = {RequestMethod.GET})
public String index() {
return "服务A";
}
}
- 服务提供者B
server.port=8081
spring.application.name=USER-SERVICE
eureka.instance.instance-id=002
eureka.instance.prefer-ip-address=true
eureka.instance.lease-expiration-duration-in-seconds=20
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.client.register-with-eureka=true
eureka.client.healthcheck.enabled=true
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://mask:111111@localhost:8088/eureka/
@SpringBootApplication
@EnableEurekaClient
@RestController
@RequestMapping("main")
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class,args);
}
@RequestMapping(value = "index", method = {RequestMethod.GET})
public String index() {
return "服务B";
}
}
- Eureka-Consumer
新增依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
创建接口 UserServiceController
@FeignClient(name = "USER-SERVICE") //name为服务名
public interface UserServiceController {
@GetMapping("main/index") //该方法映射的路径
String index();
}
server.port=8089
ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=false
eureka.client.service-url.defaultZone=http://mask:111111@localhost:8088/eureka/
@SpringBootApplication
@RestController
@EnableFeignClients
public class EurekaSpringBootConsumer {
public static void main(String[] args) {
SpringApplication.run(EurekaSpringBootConsumer.class,args);
}
@Autowired
private UserServiceController userServiceController;
@GetMapping("/rpc/test")
public String index() {
String index = userServiceController.index();
System.out.println(index);
return "OK";
}
}
访问http://localhost:8089/rpc/test
底层会根据接口方法的配置信息参数发送请求给远程的服务器这种实现比单纯的使用Ribbon更加的优雅。实际上Feign底层就是对Ribbon组件的封装。
注:在Fegin里不能传递自定义类型至GET查询参数
Feigen 熔断
默认Feign没有开启熔断策略,需要用户在配置文件中指定
- EurekaConsumer中新增配置
feign.hystrix.enabled=true
- 修改UserServiceController
@FeignClient(name = "USER-SERVICE", fallback = UserServiceFailBack.class) //name为服务名
public interface UserServiceController {
@GetMapping("main/index") //该方法映射的路径
String index();
}
- 新增UserServiceFailBack类
@Component
public class UserServiceFailBack implements UserServiceController{
@Override
public String index() {
return "熔断";
}
}
- 修改服务B使其抛出异常
@RestController
@RequestMapping("main")
public class TestController {
@RequestMapping(value = "index", method = {RequestMethod.GET})
public String index() {
int i = 1/0;
return "服务B";
}
}
启动服务多次访问http://localhost:8089/rpc/test如下图可看出服务B抛出异常后执行熔断后代码
Feign超时设置
feign.client.config.USER-SERVICE.connect-timeout=500
feign.client.config.USER-SERVICE.read-timeout=500
Hystrix Dashboard
- pom引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- application.properties新增
management.endpoints.web.exposure.include=*
- 启动类新增注解
@EnableHystrixDashboard
@EnableCircuitBreaker
配置HyStrix属性
在和Feign整合后,用户无法配置Feign的ComandProperties,但是可以通过配置Bean的形式配置
- Bean
@Bean
public SetterFactory setterFactory(){
SetterFactory setterFactory =new SetterFactory() {
@Override
public HystrixCommand.Setter create(Target<?> target, Method method) {
String groupKey = target.name();
String commandKey = Feign.configKey(target.type(), method);
HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
//设置统计指标5秒为一个时间窗口
.withMetricsRollingStatisticalWindowInMilliseconds(5000)
//操过80%失败率
.withCircuitBreakerErrorThresholdPercentage(50)
//操作5个开启短路器
.withCircuitBreakerRequestVolumeThreshold(5)
//设置线程隔离
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
//设置断路器的开启时间为5秒
.withCircuitBreakerSleepWindowInMilliseconds(5000);
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(setter);
}
};
return setterFactory;
}