springcloud(五)远程调用Feign(含源码跟踪),java基础入门答案谭晓芳

本文详细解析了Spring Cloud Feign中如何实现服务调用的熔断机制,包括使用Hystrix实现类和回调函数,以及在实际应用中的配置和案例。当cloud-user服务宕机,通过fallback策略确保请求可用性。

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

import org.

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = “cloud-user”)

public interface UserClient {

@GetMapping(value = “userInfo”)

User getUserInfo(@RequestParam(“userId”) final Integer userId);

}

@FeignClient:表示该类是一个远程调用类,交给jdk动态代理处理。

value:需要调用的服务名。

TestController:

package com.ymy.controller;

import com.ymy.entity.vo.Order;

import com.ymy.entity.vo.User;

import com.ymy.feign.UserClient;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.cloud.context.config.annotation.RefreshScope;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

@RestController

@Slf4j

@RefreshScope

public class TestController {

@Value("${test.name}")

private String name;

private UserClient userClient;

TestController(UserClient userClient){

this.userClient = userClient;

}

@GetMapping(value = “/test”)

public String test(){

return “hello:”+name+" 人生总是起起落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落!";

}

@GetMapping(value = “orderInfo”)

public Order getOrderInfo(){

Order order = new Order();

order.setId(1);

order.setUserId(2);

order.setOorderPrice(BigDecimal.valueOf(100l));

order.setNum(2);

User userInfo = userClient.getUserInfo(order.getUserId());

if(null == userInfo){

log.info(“没有查询到用户信息”);

}

order.setUser(userInfo);

return order;

}

}

6.在启动类中开启feign远程调用

package com.ymy;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication

@EnableDiscoveryClient

@EnableFeignClients

public class CloudOrderApplication {

public static void main(String[] args) {

SpringApplication.run(CloudOrderApplication.class, args);

}

}

@SpringBootApplication:springboot启动注解

@EnableDiscoveryClient:将服务注册到注册中心

@EnableFeignClients:开启feign,如果不加此注解,服务调用将不会成功。

7.启动cloud-eureka、cloud-config、cloud-user、cloud-order,测试

其中user则是cloud-order通过调用cloud-user服务拿到的,这是理想状态,如果出现意外情况呢?比如cloud-user服务宕机了会发生什么呢?,现在我停掉cloud-user服务,再次请求:

这是你会发现,服务器出现了报错,这种错误是不能出现在用户眼中的,有没有方法解决呢?

fallback 熔断机制

feign自带熔断,所以我们不需要在引入其他的依赖,feign的熔断有两种实现方式,如下:

第一种:实现类

什么是实现类呢?请注意看

UserClient是一个接口,这时候我们需要用一个类来实现这个接口

UserClientHystrix.java

package com.ymy.feign.hystrix;

import com.ymy.entity.vo.User;

import com.ymy.feign.UserClient;

import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Component;

@Component

@Slf4j

public class UserClientHystrix implements UserClient {

@Override

public User getUserInfo(Integer userId) {

//这里就是当远程调用失败时,feign会自动进入接口的实现类,就是之前所说的熔断,

// 在这里,你可以做对应的处理,比如返回一个空的User对象,或者启用备用方案,调用联外一台服务等等。

//这里我们直接返回空User对象

log.info(“请求cloud-user服务发生错误”);

return null;

}

}

还需要一步那就是在接口指明实现类:

@FeignClient(value = “cloud-user”,fallback = UserClientHystrix.class)

重启cloud-order,cloud-user保持宕机状态:

发现报错了,而且还是和第一次的错误不一致,这是什么问题导致的呢?这是因为我们没有启动feign的熔断机制,默认时关闭状态,找到bootstrap.yml文件:

feign:

hystrix:

enabled: true #开启feign熔断

重启服务再次测试:

控制台:

第二种:指定回调

指定实现类这种方式需要对每个接口做实现,如果所有的请求接口都只需要返回空的话,这样就会重复写很多一样的实现方法,所以这里引入了回调。

1.注释掉实现类,引入hystrix依赖:

org.springframework.cloud

spring-cloud-starter-netflix-hystrix

2.引入注解:@HystrixCommand

@HystrixCommand:这里指明服务调用失败时需要做什么。

fallbackMethod:指明失败之后进入哪个回调方法。

/**

  • 失败之后走这里

  • @return

*/

public Order defaultBack(){

log.info(“请求cloud-user服务发生错误”);

Order order = new Order();

order.setId(110);

order.setUserId(120);

order.setOorderPrice(BigDecimal.valueOf(1000l));

order.setNum(20);

return order;

}

3.在启动类中加入:@EnableCircuitBreaker

重启测试:

以上两种方式都可以做熔断处理,具体选择哪种,还要看业务的需求。

源码跟踪


@EnableFeignClients做了什么?

进入FeignClientsRegistrar类

一看,蒙蔽了,这么多方法,这要怎么看,其实我们需要注意的并不多,我们重点来看一下registerFeignClients方法,打上断点,启动服务:

basePackages:指的是扫描的包,下一步对扫描出来的包做遍历

请看candidateComponents的返回结果:

这里是一个集合,找到com.ymy下面有多少个被FeignClient注解标识的类。

在UserClient类中只指定了value属性,所以这里只展示value和name,随后就会将这些被@FeignClient注解标识的类交由jdk动态代理。

这是启动部分,我们再来看看调用过程

feign调用跟踪

spring-cloud-openfeign源码:https://github.com/spring-cloud/spring-cloud-openfeign

Feign源码https://github.com/OpenFeign/feign

spring-cloud-openfeign是我们项目中使用的依赖,而spring-cloud-openfeign又引入了feign依赖,这里我们只看调用过程,真正的调用过程在Feign源码中,请看:SynchronousMethodHandler.java

调用时,会走这里的代理,断点走起

Object[] argv :参数,这里我只传入了一个userId 值为2。

我们再来看看buildTemplateFromArgs.create(argv):

mutable:

varBuilder:

参数列表,Map集合,回到invoke()方法,

Options options = findOptions(argv) :拿到连接超时等信息

这是默认配置,如果我们在配置文件配置了超时时间,那么这里获取到的就是我们配置的。

进入 executeAndDecode()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值