目录
作业: 老师给的参考流程图
要求
解答
知识扩展
Feign基础原理
接口定义
代理对象生成
请求调用
请求发送
响应处理
容错与熔断
总结
作业: 老师给的参考流程图
pdf版本 【金山文档 | WPS云文档】 Feign
https://kdocs.cn/l/ctbagIyxN348
要求
结合上面的Feign调用流程总结,画图描述订单服务调用用户服务的完整流程
解答
Feign代理流程图-ProcessOn
知识扩展
Feign基础原理
Feign是一个声明式的HTTP客户端,它允许开发者通过定义接口和使用注解来简化远程服务的调用。Feign的工作原理主要涉及以下几个关键步骤:
接口定义
开发者通过定义带有Feign注解的Java接口来描述HTTP请求规范,例如使用@RequestLine
注解指定HTTP方法和URL模板。
代理对象生成
当Spring Cloud应用启动时,Feign会扫描带有@FeignClient
注解的接口,并为其生成动态代理对象。
特别注意的是需要在Springboot启动项中允许开启FeignClinet代理
package cn.tedu.charging.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
//在启动类让spring-boot帮忙开启feignClients
// 多个client
@EnableFeignClients
public class ChargingOrderApplication {
public static void main(String[] args) {
SpringApplication.run(ChargingOrderApplication.class,args);
}
}
根据我上面的作业要求 订单调用用户服务 这边直接在订单项目写了feign包,包下写了一个接口 UserClinet
package cn.tedu.charging.order.feign;
import cn.tedu.chaging.common.pojo.UserInfoVO;
import cn.tedu.chaging.common.web.JsonResult;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//userService要和nacos服务列表里的服务名称一致
@FeignClient("userService")
public interface UserClient {
//String url = "http://localhost:8083/user/info/"+userId;
@GetMapping("/user/info/{userId}")
JsonResult<UserInfoVO> getUserInfo(@PathVariable("userId") Long userId);
}
JsonResult是响应的返回体,这边我限制了其返回数据为UserInfoVo
package cn.tedu.chaging.common.web;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
/**
* //状态码 自定义的码 2000 表示成功 2001 表示失败
* //提示消息 保存失败
* //具体的数据 比如查询订单 需要把查出的订单数据返回给前端
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class JsonResult<T> {
/**
* 状态码
*/
Integer code;
/**
* 提示消息
*/
String msg;
/**
* 具体的数据
*/
T data;
/**
* 正常返回 入参 有数据和消息
* @param data
* @param msg
* @return
*/
public static JsonResult ok(Object data,String msg) {
JsonResult jsonResult = new JsonResult();
jsonResult.setCode(2000);
jsonResult.setData(data);
jsonResult.setMsg(msg);
return jsonResult;
}
/**
* 正常返回 入参只有数据
* @param data
* @return
*/
public static JsonResult ok(Object data) {
JsonResult jsonResult = new JsonResult();
jsonResult.setCode(2000);
jsonResult.setData(data);
return jsonResult;
}
}
其请求参数 UserId
响应参数获取CarId
package cn.tedu.chaging.common.pojo;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
/**
* 用户基本
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class UserInfoVO {
/**
* 车辆id
*/
Integer carId;
}
SpringCloud
请求调用
调用代理对象的方法时,实际上是在触发Feign预先设定好的HTTP请求逻辑。传入的参数会被填入到URL模板中,形成完整的HTTP请求。
我是用nacos进行服务注册的,其中我在application.yml文件写了注册名和注册地址,
为了之后的订单服务能够选择调用用户服务,可以用户服务可以改接口再次启动
order-charging包下的application.yaml
spring:
application:
name: orderService
cloud:
nacos:
server-addr: 127.0.0.1:8848
user-charging包下的application.yaml
server:
port: 8086
spring:
application:
# 服务名称 这个会在nacos服务列表里显示
name: userService
cloud:
nacos:
#服务注册地址
server-addr: 127.0.0.1:8848
HTTP请求
请求发送
Feign利用Ribbon进行负载均衡选择目标服务器,然后通过HTTP客户端(如Apache HttpClient或OkHttp)发送实际的HTTP请求。
测试一下传入参数
package cn.tedu.charging.order;
import cn.tedu.chaging.common.web.JsonResult;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.pojo.dto.CarInfoDto;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class FeignTests {
@Autowired
private UserClient userClient;
@Test
public void testGetUserInfo(){
JsonResult userInfo =
userClient.getUserInfo(1L);
System.out.println(userInfo);
}
}
响应处理
收到HTTP响应后,Feign会根据配置的解码器将其解析成相应的Java对象,然后返回给调用者。
OrderService 中Service层调用Feign返回响应数据
/**
* 通过feign的方式调用用户服务
* @param userId
* @return
*/
private CarInfoDto getCarInfoByFeign(Long userId){
JsonResult<UserInfoVO> userInfo = userClient.getUserInfo(userId);
if (userInfo != null) {
UserInfoVO data = userInfo.getData();
if (data != null) {
CarInfoDto carInfoDto = new CarInfoDto();
BeanUtils.copyProperties(data, carInfoDto);
return carInfoDto;
}
}
return null;
}
容错与熔断
Feign可以与Hystrix配合,通过设置开启熔断功能,当服务出现故障时,可以快速失败,避免连锁反应影响整个系统的稳定性。
总结
Feign的负载均衡实现主要依赖于Ribbon组件,Ribbon是一个客户端负载均衡器,而Feign则集成了Ribbon,因此当我们在Spring Cloud应用中使用Feign进行服务间调用时,自然具备了负载均衡的能力.