Feign概述
远程调用:声明式客户端
只需要声明一个抽象接口,将可以通过接口做远程调用,不需要再使用RestTemplate来调用。
调用流程:
第一步:创建springboot项目sp09-feign
第二步:添加相关依赖和sp01-commons依赖
添加sp01-commons依赖:
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>sp01-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
第三步:配置yml文件
spring:
application:
name: feign
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka,http://eureka2:2002/eureka
#调整ribbon的重试参数
ribbon:
MaxAutoRetries: 1
# 只针对item-service这一个服务有效,
# 对其他服务不应用这个配置
item-service:
ribbon:
MaxAutoRetries: 2
第四步:主程序添加@EnableFeignClients注解
package cn.tedu.sp09;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@SpringBootApplication
public class Sp09FeignApplication {
public static void main(String[] args) {
SpringApplication.run(Sp09FeignApplication.class, args);
}
}
第五步:创建ItemClient、UserClient、OrderClient接口
//根据服务id,从注册表得到主机地址
@FeignClient(name = "item-service")
public interface ItemClient {
@GetMapping("/{orderId}")
JsonResult<List<Item>> getItems(@PathVariable String orderId);
@PostMapping("/decreaseNumber")
JsonResult<?> decreaseNumber(@RequestBody List<Item> irems);//从请求协议体中获取数据
}
//根据服务id,从注册表得到主机地址
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/{userId}")
JsonResult<User> getUser(@PathVariable Integer userId);
// /8/score?score=1000
@GetMapping("/{userId}/score")
JsonResult<?> addScore(@PathVariable Integer userId,
@RequestParam Integer score);
}
@FeignClient(name = "order-service")
public interface OrderClient {
@GetMapping("/{orderId}")
JsonResult<Order> getOrder(@PathVariable String orderId);
@GetMapping("/")
JsonResult<?> addOrder();
}
第六步:创建FeignController
类似于springmvc的controller配置结构。
package cn.tedu.sp09.controller;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp09.feign.ItemClient;
import cn.tedu.sp09.feign.OrderClient;
import cn.tedu.sp09.feign.UserClient;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@Slf4j
public class FeignController {
@Autowired
private ItemClient itemClient;
@Autowired
private OrderClient orderClient;
@Autowired
private UserClient userClient;
@GetMapping("/item-service/{orderId}")
public JsonResult<List<Item>> getItems(@PathVariable String orderId){
return itemClient.getItems(orderId);
}
@PostMapping("/item-service/decreaseNumber")
public JsonResult<?> decreaseNumber(@RequestBody List<Item> items){
return itemClient.decreaseNumber(items);
}
@GetMapping("/user-service/{userId}")
public JsonResult<User> getUser(@PathVariable Integer userId){
return userClient.getUser(userId);
}
@GetMapping("/user-service/{userId}/score")
public JsonResult<?> addScore(@PathVariable Integer userId,Integer score){
return userClient.addScore(userId, score);
}
@GetMapping("/order-service/{orderId}")
public JsonResult<Order> getOrder(@PathVariable String orderId){
return orderClient.getOrder(orderId);
}
@GetMapping("/order-service/")
public JsonResult<?> addOrder(){
return orderClient.addOrder();
}
}
第七步:启动服务,进行测试
http://localhost:3001/item-service/35
Feign集成Ribbon
feign已默认开启ribbon负载均衡和重试机制。
可在yml中配置ribbon的超时和重试时间。
#全局配置
ribbon:
ConnectTimeout: 1000
ReadTimeout: 1000
#单体服务器配置
item-service:
ribbon:
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 2
ConnectTimeout: 1000
ReadTimeout: 500
Feign集成Hystrix
Feign默认不启用Hystrix,不推荐启用Hystrix。
第一步:sp09中pom添加Hystrix起步依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
第二步:yml中启用hystrix
# 启用hystrix
feign:
hystrix:
enabled: true
第三步:主程序上添加@EnableCircuitBreaker注解,启用hystrix断路器。
package cn.tedu.sp09;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableCircuitBreaker
@EnableFeignClients
@SpringBootApplication
public class Sp09FeignApplication {
public static void main(String[] args) {
SpringApplication.run(Sp09FeignApplication.class, args);
}
}
添加降级
调用超时或失败则访问降级类进行输出返回。
第一步:ItemClient、UserClient、OrderClient接口中注解内添加降级类
//根据服务id,从注册表得到主机地址
@FeignClient(name = "item-service",fallback=ItemClientFB.class)
public interface ItemClient {
@GetMapping("/{orderId}")
JsonResult<List<Item>> getItems(@PathVariable String orderId);
@PostMapping("/decreaseNumber")
JsonResult<?> decreaseNumber(@RequestBody List<Item> irems);//从请求协议体中获取数据
}
@FeignClient(name = "order-service",fallback=OrderClientFB.class)
@FeignClient(name = "user-service",fallback=UserClientFB.class)
第二步:创建ItemClient、UserClient、OrderClient接口的降级实现类ItemClientFB、UserClientFB、OrderClientFB。
添加@Component注解将降级类交给spring管理,并重写接口类的方法,设置降级输出。
package cn.tedu.sp09.feign;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.web.util.JsonResult;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ItemClientFB implements ItemClient{
@Override
public JsonResult<List<Item>> getItems(String orderId) {
return JsonResult.err().msg("无法获取订单商品列表");
}
@Override
public JsonResult<?> decreaseNumber(List<Item> irems) {
return JsonResult.err().msg("无法修改商品库存");
}
}
package cn.tedu.sp09.feign;
import cn.tedu.sp01.pojo.User;
import cn.tedu.web.util.JsonResult;
import org.springframework.stereotype.Component;
@Component
public class UserClientFB implements UserClient{
@Override
public JsonResult<User> getUser(Integer userId) {
return JsonResult.err().msg("无法获取用户信息");
}
@Override
public JsonResult<?> addScore(Integer userId, Integer score) {
return JsonResult.err().msg("无法增加用户积分");
}
}
package cn.tedu.sp09.feign;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.web.util.JsonResult;
import org.springframework.stereotype.Component;
@Component
public class OrderClientFB implements OrderClient{
@Override
public JsonResult<Order> getOrder(String orderId) {
return JsonResult.err().msg("无法获取商品订单");
}
@Override
public JsonResult<?> addOrder() {
return JsonResult.err().msg("无法保存订单");
}
}
第三步:启用服务器进行测试
当访问服务出错时,访问降级类进行输入。
http://localhost:3001/item-service/35
添加熔断
降级配置完成,熔断自动开启。
添加监控
第一步:添加actuator依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
第二步:在yml中设置暴露端点配置
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: hystrix.stream
第三步:访问监控测试
http://localhost:3001/actuator/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。