远程调用 OpenFeign
##### 什么是OpenFeign
Feign 是Springcloud 提供一个声明式的伪Http客户端 它使得调用远程服务就像调用本地服务一样简单 只需要创建一个接口 并且添加注解就可以 Nacos 很好的兼容Feign Feign 默认集成了Ribbon 所以在Nacos 下使用Fegin 默认就实现了负载均衡的效果
如何集成OpenFeign
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")
public interface ProductFeignApi {
@GetMapping("product")
Product findByPid(@RequestParam("pid") Long pid);
}
4.0 在启动类上开启远程调用
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServer {
public static void main(String[] args) {
SpringApplication.run(OrderServer.class,args);
}
}
5.0 修改OrderServiceImpl.java的远程调用方法
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductFeignApi productFeignApi; //把它注入
@Override
public Order createOrder(Long productId,Long userId) {
log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);
//远程调用商品微服务,查询商品信息
Product product = productFeignApi.findByPid(productId); //调方法就可
log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));
//创建订单并保存
Order order = new Order();
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 请求
OpenFeign 超时配置
在服务调用端 去加上这段配置 该配置是在顶级下 并不是在cloud 下面 建议使用下面这个最终的配置
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
product-service: # 调用的提供者的名称
#配置首台服务器重试1次
MaxAutoRetries: 1
#配置其他服务器重试两次
MaxAutoRetriesNextServer: 2
#链接超时时间
ConnectTimeout: 500
#请求处理时间
ReadTimeout: 2000
#每个操作都开启重试机制
OkToRetryOnAllOperations: true
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
OpenFeign 重试次数配置
在服务调用端 去加上这个段配置 使用这个最终的配置
product-service: # 调用的提供者的名称
ribbon:
#配置首台服务器重试1次
MaxAutoRetries: 1
#配置其他服务器重试两次
MaxAutoRetriesNextServer: 2
#链接超时时间
ConnectTimeout: 500
#请求处理时间
ReadTimeout: 2000
#每个操作都开启重试机制
OkToRetryOnAllOperations: true
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
这里需要你注意的一点是,如果你同时配置了全局超时规则和针对某个特定服务的超时规则,那么后者的配置会覆盖全局配置,并且优先生效