2026/4/7 17:28:56
网站建设
项目流程
html网站设计源码,ucenter整合wordpress,住房及城乡建设部网站,破解asp网站后台地址1. OpenFeign 核心原理 用一句话总结#xff1a;OpenFeign 是一个声明式的 HTTP 客户端#xff0c;通过动态代理将接口方法映射为 HTTP 请求。
它的核心工作流程如下#xff1a;
启动扫描#xff1a;Spring Boot 启动时#xff0c;EnableFeignClients 注解会扫描所有标有…1. OpenFeign 核心原理用一句话总结OpenFeign 是一个声明式的 HTTP 客户端通过动态代理将接口方法映射为 HTTP 请求。它的核心工作流程如下启动扫描Spring Boot 启动时EnableFeignClients注解会扫描所有标有FeignClient的接口。动态代理 (Dynamic Proxy)Spring 会为这些接口生成动态代理对象JDK Proxy并注入到 Spring 容器中。请求拦截当你调用接口方法如orderService.createOrder()时代理对象拦截该调用。构造请求根据接口上的注解GetMapping,PathVariable等解析出 URL、Method、Headers、Body 等信息构建一个 HTTP Request Template。服务发现与负载均衡Feign 拦截到请求后通过服务名Service Name去 Nacos 查找可用的 IP 列表。结合Spring Cloud LoadBalancer(在 Boot 3.x 中替代了 Ribbon) 选择一个最佳实例。发送请求通过底层的 HTTP 客户端默认是 JDKHttpURLConnection生产环境通常替换为OkHttp或Apache HttpClient发送真正的网络请求。解码响应拿到 HTTP 响应后通过Decoder(通常是 Jackson) 将 JSON 字符串反序列化成你定义的 Java 对象。2. Java 代码实战假设场景你的service-order(订单服务)需要调用service-stock(库存服务)来扣减库存。第一步引入依赖 (pom.xml)在service-order(消费者) 中添加 OpenFeign 和 负载均衡器依赖。注意Spring Boot 3.x (Spring Cloud 2022.x) 彻底移除了 Ribbon必须确保有 LoadBalancer。dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependency/dependencies第二步开启 Feign (启动类)在service-order的启动类上添加注解。SpringBootApplicationEnableFeignClients// 开启 Feign 扫描publicclassOrderApplication{publicstaticvoidmain(String[]args){SpringApplication.run(OrderApplication.class,args);}}第三步编写 Feign 接口 (核心)创建一个接口这就相当于以前写的 Controller 的方法签名但是这里没有方法体。packagecom.example.order.feign;importcom.example.order.dto.StockDTO;// 假设有一个传输对象importorg.springframework.cloud.openfeign.FeignClient;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PathVariable;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestParam;// name: 指定要调用的 Nacos 服务名称 (非常重要必须匹配)// path: 可选如果对方 Controller 类上有 RequestMapping(/stock)这里可以统一加FeignClient(nameservice-stock,path/stock)publicinterfaceStockFeignClient{/** * 查询库存 * 对应 GET http://service-stock/stock/{id} */GetMapping(/{id})StockDTOgetById(PathVariable(id)Longid);/** * 扣减库存 * 对应 POST http://service-stock/stock/deduct?countxxx */PostMapping(/deduct)Stringdeduct(RequestParam(count)Integercount);}第四步在业务代码中使用在OrderService中直接注入接口使用就像调用本地代码一样。ServicepublicclassOrderService{AutowiredprivateStockFeignClientstockFeignClient;// 注入动态代理对象publicvoidcreateOrder(LongstockId){// 1. 远程调用查询库存StockDTOstockstockFeignClient.getById(stockId);System.out.println(当前库存stock.getCount());// 2. 远程调用扣减库存stockFeignClient.deduct(1);}}3. 生产环境必配日志与超时默认情况下OpenFeign 是“哑巴”不打印日志且“急性子”超时时间短这在开发和生产中都不好用。3.1 开启详细日志Feign 的日志级别分为NONE(默认),BASIC,HEADERS,FULL。开发环境建议开FULL。importfeign.Logger;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;ConfigurationpublicclassFeignConfig{BeanpublicLogger.LevelfeignLoggerLevel(){returnLogger.Level.FULL;// 打印 请求头、请求体、响应头、响应体}}注意还需要在application.yml中将该 Feign 接口包路径的日志级别设为 DEBUG否则 Logback 不会输出。logging:level:com.example.order.feign:DEBUG3.2 配置超时时间spring:cloud:openfeign:client:config:default:# 对所有服务生效也可以替换为具体的服务名 service-stockconnect-timeout:5000# 连接超时 (毫秒)read-timeout:5000# 读取/处理超时 (毫秒)logger-level:full# 也可以在这里配日志级别2.OpenFeign 拦截器 (RequestInterceptor)1. 原理OpenFeign 允许我们定义一个或多个拦截器 (RequestInterceptor)。在 Feign 生成 HTTP 请求模板 (RequestTemplate) 之后、真正发送请求之前这些拦截器会被执行。核心作用Token 中继。场景用户访问 Service-A (带了 Token)Service-A 调用 Service-B。如果不做处理Service-B 会报“未登录”因为 Token 在 A 这里断掉了。拦截器可以把 A 收到的 Token 塞到去往 B 的请求头里。2. Java 代码实战步骤一编写拦截器类packagecom.example.order.config;importfeign.RequestInterceptor;importfeign.RequestTemplate;importjakarta.servlet.http.HttpServletRequest;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.context.request.RequestContextHolder;importorg.springframework.web.context.request.ServletRequestAttributes;ConfigurationpublicclassFeignTokenInterceptorimplementsRequestInterceptor{Overridepublicvoidapply(RequestTemplatetemplate){// 1. 获取当前请求的上下文即用户发给 Order 服务的请求ServletRequestAttributesattributes(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();if(attributes!null){HttpServletRequestrequestattributes.getRequest();// 2. 获取原始请求中的 TokenStringtokenrequest.getHeader(Authorization);// 3. 将 Token 传递给下游服务Stock 服务if(token!null){template.header(Authorization,token);}}// 也可以加一些自定义的内部 Headertemplate.header(X-From-Service,service-order);}}步骤二生效配置只要加上Configuration这个拦截器就是全局生效的所有 Feign 接口都会自动带上 Token。3.Fallback 兜底机制 (结合 Sentinel)在 Spring Cloud Alibaba 中Feign 的熔断降级官方推荐使用Sentinel。1. 原理OpenFeign 会利用动态代理在发送请求时包裹一层 Sentinel 的资源保护逻辑。正常情况执行远程调用。异常情况网络超时、对方报错、对方宕机捕获异常不再抛给前端而是执行配置好的fallback逻辑返回默认值。2. 准备工作引入 Sentinel 依赖 (pom.xml)dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId/dependency开启 Sentinel 对 Feign 的支持 (application.yml)这是最容易忘的一步默认是关闭的。spring:cloud:openfeign:client:config:default:connect-timeout:2000read-timeout:2000sentinel:enabled:true# 【关键】开启 Sentinel 对 Feign 的支持3. Java 代码实战 (推荐使用 FallbackFactory)Feign 提供了两种方式fallback(简单类) 和fallbackFactory(工厂类)。**强烈推荐使用fallbackFactory**因为它可以拿到具体的异常信息是超时了还是 404还是 500方便记录日志。步骤一定义 Feign 接口FeignClient(nameservice-stock,fallbackFactoryStockFeignClientFallbackFactory.class)publicinterfaceStockFeignClient{PostMapping(/deduct)Stringdeduct(RequestParam(count)Integercount);}步骤二编写 FallbackFactory 实现类这个类必须注册为 Spring Bean (Component)。packagecom.example.order.feign.fallback;importcom.example.order.feign.StockFeignClient;importorg.springframework.cloud.openfeign.FallbackFactory;importorg.springframework.stereotype.Component;importlombok.extern.slf4j.Slf4j;Slf4jComponentpublicclassStockFeignClientFallbackFactoryimplementsFallbackFactoryStockFeignClient{OverridepublicStockFeignClientcreate(Throwablecause){// 这里可以拿到具体的异常 cause// 返回一个实现了原接口的匿名内部类returnnewStockFeignClient(){OverridepublicStringdeduct(Integercount){// 1. 记录降级日志方便运维排查log.error(调用库存服务失败触发兜底降级。原因{},cause.getMessage());// 2. 返回兜底数据// 比如返回一个特定的 JSON 结构告诉前端系统繁忙请稍后// 或者如果是查询操作可以返回缓存中的旧数据returnfallback-value: 库存扣减失败服务忙;}};}}总结与最佳实践功能核心类/接口作用关键配置拦截器RequestInterceptor传递 Token、TraceIDConfiguration全局注入兜底(简单)fallback X.class仅返回默认值不知异常原因feign.sentinel.enabled: true兜底(推荐)fallbackFactory X.class返回默认值 获取异常堆栈feign.sentinel.enabled: true开发建议必须要有兜底永远不要相信网络和下游服务是 100% 稳定的。没有兜底的微服务就是裸奔。兜底逻辑要简单Fallback 方法里的逻辑不能太复杂例如不要再去调数据库或另一个远程服务否则兜底逻辑自己也挂了就尴尬了。通常只做日志记录 返回静态默认值。