springboot中使用feign

本文详细介绍了如何使用Feign进行微服务间的调用,包括添加依赖、配置类、接口定义及容错处理等内容,提供了丰富的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近使用feign大概记录下使用过程
1.添加依赖

             <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-core</artifactId>
                <version>9.7.0</version>
            </dependency>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-slf4j</artifactId>
                <version>9.5.0</version>
            </dependency>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-hystrix</artifactId>
                <version>9.5.0</version>
            </dependency>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-jackson</artifactId>
                <version>9.5.0</version>
            </dependency>

2.添加配置类

			@Configuration
			public class WebApiConfig {
			
			    /**
			     * gps服务地址
			     */
			    @Value("${application.gpsWebApi.url}")
			    private String gpsWebApiUrl;

				//@Autowired
   			    //private GpsWebApiServiceFallback gpsWebApiServiceFallback;  接口调用失败的容错实现类
			
			
			    @Bean
			    GpsWebApiService gpsClient() throws Exception {
			        return HystrixFeign.builder()
			                .decoder(new JacksonDecoder())
			                .encoder(new JacksonEncoder())
			                .setterFactory((target, method) ->
			                //new SetterFactory.Default().create(target,method).andThreadPoolPropertiesDefaults(Setter().withCoreSize(30)). 可以设置大小
			                        new SetterFactory.Default().create(target, method).
			                                andCommandPropertiesDefaults(HystrixCommandProperties.defaultSetter().
			                                        withExecutionTimeoutInMilliseconds(1000*60)))
			                						.target(GpsWebApiService.class, gpsWebApiUrl);
			                						//.target(GpsWebApiService.class, gpsWebApiUrl, gpsWebApiServiceFallback);可以添加接口访问失败的容错机制
			    }
			}
			
@Component
public class GpsWebApiServiceFallback implements FallbackFactory<GpsWebApiService> {

    private Logger logger = LoggerFactory.getLogger(GpsWebApiServiceFallback.class);

    @Override
    public GpsWebApiService create(Throwable throwable) {

        logger.error("GpsWebApiServiceFallback.throwable is error", throwable);
        return new GpsWebApiService() {
            @Override
            public ResultVo<String> setBusiness(int terminalType, String terminalId, GpsBusinessDto gpsBusinessDto) {
                ResultVo<String> resultVo = new ResultVo<>();
                resultVo.resultFail("失败");
                logger.error("GpsWebApiServiceFallback.setBusiness terminalType:" + terminalType + ";terminal:" + terminalId + ";gpsBusinessDto" + FastJsonUtils.toJSONString(gpsBusinessDto));
                return resultVo;
            }
}

1.当然使用HystrixFeign默认处理线程池中核心线程数数是10,默认最大的队列是100,具体根据业务去处理,可在andThreadPoolPropertiesDefaults(Setter().withCoreSize(30))设置核心线程数,最大线程数以及最大队列大小
2.可添加服务调用失败的一些容错降级处理 ,在target(GpsWebApiService.class, gpsWebApiUrl, gpsWebApiServiceFallback),
自定义的GpsWebApiServiceFallback需要实现 FallbackFactory <T>,T就是接口类,然后实现调用接口失败的一些容错

源码;

static HystrixThreadPoolProperties.Setter getUnitTestPropertiesBuilder() {
            return (new HystrixThreadPoolProperties.Setter()).withCoreSize(10).withKeepAliveTimeMinutes(1).withMaxQueueSize(100).withQueueSizeRejectionThreshold(10).withMetricsRollingStatisticalWindowInMilliseconds(10000).withMetricsRollingStatisticalWindowBuckets(10);
        }

3.创建接口 get和post请求都有,单个参数和多个参数都有,但是在多个参数中@reqeustBody只能有一个

public interface GpsWebApiService {

    /*
     *
     * @param terminalId
     * @param gpsBusinessDto
     * @return
     */
    @Headers({"Content-Type: application/json;charset=utf-8", "Accept: application/json;charset=utf-8"})
    @RequestLine("POST /setBusiness?terminalId={terminalId}")
    ResultVo<String> setBusiness(@Param("terminalId") String terminalId, @RequestBody GpsBusinessDto gpsBusinessDto);

    /*
    *
     * @param terminalId
     * @return
     */
    @RequestLine("POST /readBusiness?terminalId={terminalId}")
    ResultVo<GpsBusinessDto> readBusiness(@Param("terminalId") String terminalId);

    /*
    * 
     * @param terminalId
     * @param terminalParamsInfoDto
     * @return
     */
    @Headers({"Content-Type: application/json;charset=utf-8", "Accept: application/json;charset=utf-8"})
    @RequestLine("POST /setTerminalArgs?terminalId={terminalId}")
    ResultVo<String> setTerminalArgs(@Param("terminalId") String terminalId, @RequestBody TerminalParamsInfoDto terminalParamsInfoDto);

    /*
     *
     * @param terminalId
     * @return
     */
    @RequestLine("POST /readTerminalArgs?terminalId={terminalId}")
    ResultVo<TerminalParamsInfoDto> readTerminalArgs(@Param("terminalId") String terminalId);

    /*//一般的get请求使用url参数清洁
    @RequestLine("GET /hello?arg={arg}")
    ResultVo<String> getHello(@Param("arg") String arg);

    //get请求中使用restful,调用对应的服务也要用restful风格接受
    @RequestLine("GET /hello/{arg}")
    ResultVo<String> getHelloWorld(@Param("arg") String arg);*/
}


5.对应外部api接口

@RestController
@RequestMapping(value = "/gps")
@CrossOrigin
@Api(value = "GpsController", description = "xxxx")
public class GpsController {

    @ApiOperation(value = "xxxxx")
    @PostMapping("/setBusiness")
    public SyncBean<String> setBusiness(@RequestParam(value = "terminalId") @ApiParam(value = "xxx, required = true) String terminalId,
                                        @RequestBody @ApiParam(value = "xxx", required = true) BusinessBean businessData) {
        SyncBean<String> result = null;
        try {
            result = gpsWebApi.setBusinessData(terminalId, businessData);
        } catch (Exception e) {
        }
        return result;
    }

    @ApiOperation(value = "xxx")
    @PostMapping("/readBusiness")
    public SyncBean<BusinessBean> readBusiness(@RequestParam(value = "terminalId")
                                               @ApiParam(value = "xxxx", required = true) String terminalId) {
        SyncBean<BusinessBean> syncBean = null;
        try {
            GpsWebApi gpsWebApi = new GpsWebApi();
            syncBean = gpsWebApi.readBusiness(terminalId);
        } catch (Exception e) {
        }
        return syncBean;
    }
    }
<think>嗯,用户之前让我提供一个3-5年Java开发工程师的简历模板,现在又问了关于Spring Boot项目中Feign是否负责负载均衡的问题。看起来用户可能是在准备面试或者实际工作中遇到了相关技术问题,需要深入了解Feign和负载均衡的关系。 首先,我需要确认Feign在Spring Cloud中的作用。Feign是一个声明式的HTTP客户端,用来简化服务之间的调用。它通常和Ribbon、Eureka等组件一起使用。负载均衡方面,Ribbon负责客户端的负载均衡,而Feign默认集成了Ribbon,所以用户可能在使用Feign时已经间接用到了负载均衡功能,但Feign本身并不处理负载均衡的具体逻辑,而是依赖Ribbon来实现。 然后,用户可能混淆了Feign和Ribbon的职责。需要明确说明Feign的角色是简化服务调用,而负载均衡由Ribbon处理。此外,在Spring Cloud新版本中,例如从2020.0.0开始,Ribbon被移除了,替代方案是Spring Cloud LoadBalancer,这时候Feign会转而使用LoadBalancer来实现负载均衡,所以需要提到这一点变化。 还要考虑用户的实际使用场景,是否在使用旧版Spring Cloud,或者已经升级到新版本。可能需要给出配置示例,说明如何正确使用Feign和负载均衡组件,以及如何检查依赖关系,确保功能正常。 用户可能想知道如何验证Feign是否启用了负载均衡,或者遇到负载均衡不生效的问题,所以需要提供一些排查步骤,比如检查是否有Ribbon或LoadBalancer的依赖,服务发现是否正确配置等。 最后,要确保回答结构清晰,分点说明,帮助用户逐步理解Feign和负载均衡的关系,同时指出版本变化带来的影响,避免用户在实际应用中遇到兼容性问题。</think>在Spring Boot/Spring Cloud项目中,Feign本身不直接负责负载均衡,但默认情况下它与负载均衡组件**深度集成**,以下是关键技术细节说明: --- ### 🔍 核心机制 1. **Feign的定位** - 本质是**声明式HTTP客户端**(通过接口+注解定义服务调用) - 主要职责:封装HTTP请求细节,实现服务间RESTful调用 2. **负载均衡实现方** - 传统方案:通过与**Ribbon**集成实现客户端负载均衡 - 新版方案:与**Spring Cloud LoadBalancer**集成(Spring Cloud 2020.0.0+弃用Ribbon后) --- ### ⚙️ 工作流程(以传统Ribbon方案为例) ```java @FeignClient(name = "payment-service") // 服务名对应注册中心的应用名称 public interface PaymentClient { @GetMapping("/payments/{id}") Payment getPayment(@PathVariable Long id); } ``` 1. 服务发现:通过`name`属性从注册中心(如Eureka/Nacos)获取服务实例列表 2. 负载均衡:Ribbon根据策略(轮询/随机/加权等)选择目标实例 3. 请求转发:Feign将最终请求发送到选定实例 --- ### 🔧 关键配置项 ```yaml # 开启负载均衡(旧版) feign: client: config: default: connectTimeout: 5000 readTimeout: 5000 # Ribbon配置(传统方案) ribbon: eureka: enabled: true NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule # LoadBalancer配置(新版) spring: cloud: loadbalancer: configurations: zone-preference ``` --- ### ✅ 验证负载均衡生效 1. 注册中心确认有多个相同服务实例 2. 在Feign调用时观察日志: ``` LoadBalancerFeignClient - Using service instance: 192.168.1.101:8080 ``` 3. 多次调用时IP:Port应轮换出现 --- ### ⚠️ 常见问题 1. **新版兼容性** 若使用Spring Cloud 2020.0.0+版本,需显式添加依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> ``` 2. **超时配置优先级** Feign的超时设置会覆盖Ribbon/LoadBalancer的配置,需要保持一致性 3. **自定义策略** 可通过实现`IRule`接口(Ribbon)或`ReactorLoadBalancer`(LoadBalancer)定制算法 --- ### 📌 结论 - Feign**间接实现**负载均衡,需配合服务注册发现组件使用 - 实际负载均衡逻辑由Ribbon或Spring Cloud LoadBalancer执行 - 生产环境建议结合熔断器(Hystrix/Sentinel)使用保证系统健壮性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值