远程调用 Feign
什么是Feign
Feign 是Springcloud 提供一个声明式的伪Http客户端 它使得调用远程服务就像调用本地服务一样简单 只需要创建一个接口 并且添加注解就可以 Nacos 很好的兼容Feign Feign 默认集成了Ribbon 所以在Nacos 下使用Fegin 默认就实现了负载均衡的效果
如何集成Feign
1.0 三板斧操作
2.0 加依赖
<!--fegin组件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
3.0 使用注解 这个远程调用需要写接口
package com.itzhouwei.shop.order.feign;import com.itzhouwei.shop.domain.Product;import com.itzhouwei.shop.order.feign.facback.ProductFeignFacback;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.openfeign.FeignClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;/****
* 使用FeignApi 调用
*/@FeignClient(name="product-service")publicinterfaceProductFeignApi{@GetMapping("product")
ProductfindByPid(@RequestParam("pid") Long pid);}
4.0 在启动类上开启远程调用
@SpringBootApplication@EnableDiscoveryClient@EnableFeignClientspublicclassOrderServer{publicstaticvoidmain(String[] args){
SpringApplication.run(OrderServer.class,args);}}
5.0 修改OrderServiceImpl.java的远程调用方法
@Service@Slf4jpublicclassOrderServiceImplimplementsOrderService{@Autowiredprivate OrderDao orderDao;@Autowiredprivate ProductFeignApi productFeignApi;//把它注入@Overridepublic OrdercreateOrder(Long productId,Long userId){
log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);//远程调用商品微服务,查询商品信息
Product product= productFeignApi.findByPid(productId);//调方法就可
log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));//创建订单并保存
Order order=newOrder();
order.setUid(userId);
order.setUsername("zw");
order.setPid(productId);
order.setPname(product.getPname());
order.setPprice(product.getPprice());
order.setNumber(1);
orderDao.save(order);
log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));return order;}}
Feign 调用原理
底层使用了建造者和代理设计模式等等
简单来说 调用原理 我简单理解为
- 通过反射机制拿到当前代理类实现的接口XXXFeignApi
- 接口通过反射方式拿到接口上的注解
@FeignClient(name = "product-service")
取出该注解中的值 - 通过反射拿到接口中的方法上面的注解
@GetMapping("product")
进行取出值 - 通过反射拿接口中方法参数注解
@RequestParam("pid")
取出值 - 进行拼接路径 URL地址
- 根据服务的名字去注册中心去找到节点信息
- 根据你配置的负载均衡策略 选择一个节点
- 把路径中的服务名字替换掉ip:prot 信息
- 使用RestTemplat 取发送http 请求
Feign 超时配置
在服务调用端 去加上这段配置 该配置是在顶级下 并不是在cloud 下面 建议使用下面这个最终的配置
feign:client:config:default:connectTimeout:5000readTimeout:5000product-service:# 调用的提供者的名称#配置首台服务器重试1次MaxAutoRetries:1#配置其他服务器重试两次MaxAutoRetriesNextServer:2#链接超时时间ConnectTimeout:500#请求处理时间ReadTimeout:2000#每个操作都开启重试机制OkToRetryOnAllOperations:trueNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Feign 重试次数配置
在服务调用端 去加上这个段配置 使用这个最终的配置
product-service:# 调用的提供者的名称ribbon:#配置首台服务器重试1次MaxAutoRetries:1#配置其他服务器重试两次MaxAutoRetriesNextServer:2#链接超时时间ConnectTimeout:500#请求处理时间ReadTimeout:2000#每个操作都开启重试机制OkToRetryOnAllOperations:trueNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
这里需要你注意的一点是,如果你同时配置了全局超时规则和针对某个特定服务的超时规则,那么后者的配置会覆盖全局配置,并且优先生效