1.feign 声明式客户端接口
微服务应用中 ribbon和hystrix总是同时出现 feign整合了两者 并提供了声明式消费者客户端
用feign代替hystrix+ribbon
新建项目
添加依赖
编辑yml文件
spring:
application:
name: feign
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
主程序添加@EnableDiscoverClient和@EnableFeignClients
注解
Feign远程调用
Feign提供了声明式客户端 只需要定义一个接口 就可以通过
接口做远程调用 具体调用代码通过动态代理添加
// 调用商品服务的远程调用接口
// 通过注解配置3件事:调用哪个服务,调用什么路径,向这个路径提交什么参数
@FeignClient(name="item-service")
public interface ItemFeignClient {
@GetMapping("/{orderId}")
JsonResult<List<Item>> getItems(@PathVariable String orderId);
}
添加Feign声明式客户端
1.OpenFeign依赖
2.启动类@EnableFeignClients
3.定义声明式客户端接口
ItemFeignClient
UserFeignClient
OrderFeignClient
4.添加一个测试用的控制器 使用三个声明式客户端接口调用远程服务
FeignController
////////////////////////
package cn.tedu.sp09.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp09.service.ItemFeignService;
import cn.tedu.sp09.service.OrderFeignService;
import cn.tedu.sp09.service.UserFeignService;
import cn.tedu.web.util.JsonResult;
@RestController
public class FeignController {
@Autowired
private ItemFeignService itemService;
@Autowired
private UserFeignService userService;
@Autowired
private OrderFeignService orderService;
@GetMapping("/item-service/{orderId}")
public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
return itemService.getItems(orderId);
}
@PostMapping("/item-service/decreaseNumber")
public JsonResult decreaseNumber(@RequestBody List<Item> items) {
return itemService.decreaseNumber(items);
}
/
@GetMapping("/user-service/{userId}")
public JsonResult<User> getUser(@PathVariable Integer userId) {
return userService.getUser(userId);
}
@GetMapping("/user-service/{userId}/score")
public JsonResult addScore(@PathVariable Integer userId, Integer score) {
return userService.addScore(userId, score);
}
/
@GetMapping("/order-service/{orderId}")
public JsonResult<Order> getOrder(@PathVariable String orderId) {
return orderService.getOrder(orderId);
}
@GetMapping("/order-service")
public JsonResult addOrder() {
return orderService.addOrder();
}
}
调用流程
feign+ribbon负载均衡和重试
Feign默认启用了Ribbon的负载均衡和重试 无需额外配置
默认重试参数:
MaxAutoRetries=0
MaxAutoRetriesNextServer=1
ReadTimeout=1000
重试参数配置
对所有的服务都有效
ribbon:
MaxAutoRetries: 1
对item-service单独配置 对其他服务无效
item-service:
ribbon:
MaxAutoRetries: 0
ribbon.xxx 全局配置
item-service.ribbon.xxx 对特定的服务实例的配置
/////////////////////////////////////////////
feign+hystrix降级
feign启用hystrix
feign默认没有启动hystrix 添加配置 启用hystrix
yml文件添加配置
feign:
hystrix:
enabled: true
启用hystrix后 访问服务
[http://localhost:3001/item-service/35]
默认1秒会快速失败,没有降级方法时,会显示白板页
可以添加配置 暂时减小降级超时时间 以便后续对降级进行测试
feign:
hystrix:
enabled: true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 500
feign+hystrix降级
feign远程接口中的指定降级类
远程调用失败 会执行降级类中的代码
feign+hystrix监控和熔断测试
修改sp09-feign项目
主程序添加@EnableCircuitBreaker
////
配置actuator 暴露hystrix.stream监控端点
1.查看pom.xml 确认已经添加了actuator依赖
2.yml文件配置暴露 hystrix.stream端点
启动服务 查看监控端点
hystrix dashboard
启动hystrix dashboard服务 填入feign监控路径 开启监控
访问http://localhost:4001/hystrix
填入feign监控路径
http://localhost:3001/actuator/hystrix.stream
访问微服务 以产生监控数据
熔断测试
用ab工具 以并发50次 来发送20000个请求
ab -n 20000 -c 50 http://localhost:3001/item-service/35
断路为open状态 所有的请求都会被降级
直接降级执行callback方法
OrderService调用商品库存服务和用户服务
修改sp04-orderservice项目 添加feign 调用item service和user service
- pom.xml
- application.yml
- 主程序
- ItemFeignService
- UserFeignService
- ItemFeignServiceFB
- UserFeignServiceFB
- OrderServiceImpl
右击项目编辑起步依赖
actuator
feign
hystrix
package cn.tedu.sp04.order.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp01.service.OrderService;
import cn.tedu.sp04.order.feignclient.ItemFeignService;
import cn.tedu.sp04.order.feignclient.UserFeignService;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private ItemFeignService itemService;
@Autowired
private UserFeignService userService;
@Override
public Order getOrder(String orderId) {
//调用user-service获取用户信息
JsonResult<User> user = userService.getUser(7);
//调用item-service获取商品信息
JsonResult<List<Item>> items = itemService.getItems(orderId);
Order order = new Order();
order.setId(orderId);
order.setUser(user.getData());
order.setItems(items.getData());
return order;
}
@Override
public void addOrder(Order order) {
//调用item-service减少商品库存
itemService.decreaseNumber(order.getItems());
//TODO: 调用user-service增加用户积分
userService.addScore(7, 100);
log.info("保存订单:"+order);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。