从0到1学SpringCloud——08 通过fegin实现微服务之间请求调用

目录

一、前言

1、关于Fegin

2、注意事项

3、POM依赖

二、编码实现

1、启动类

2、创建openfeign接口

3、Controller代码

4、回调工厂

三、文件配置

1、Feign接口日志级别

2、超时时间

四、性能优化


一、前言

上一篇介绍了通过RestTemplate实现微服务之间请求调用,本篇介绍通过fegin的方式如何在微服务之间发送请求。

1、关于Fegin

1、Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端。

2、Fegin内置Ribbon用来做客户端负载均衡。
3、使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
4、Spring Cloud 在Feign的基础上支持了Spring MVC的注解,也就是OpenFeign。

2、注意事项

1、OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口。
2、@RequesMapping不能在类名上与@FeignClient同时使用。

3、POM依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 熔断降级 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

二、编码实现

1、启动类

启动类上要加 @EnableFeignClients

/**
 * @ClassName: MsgApplication
 * @Description msg启动类
 * @author 月夜烛峰
 * @date 2022/7/22 08:53
 */
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class MsgApplication {
    public static void main(String[] args) {
        SpringApplication.run(MsgApplication.class, args);
    }
}

否则定义的fegin接口不能自动装配,也即是不会被spring接管,报错信息如下:

2、创建openfeign接口

package com.zhufeng.web.api;

import com.alibaba.fastjson.JSONObject;
import com.zhufeng.web.fallback.UserFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @ClassName: FeignUserApi
 * @Description 对外提供api接口
 * @author 月夜烛峰
 * @date 2022/8/31 16:55
 */
@FeignClient(value = "zhufeng-web-user", fallbackFactory = UserFallbackFactory.class)
public interface ShowUserApi {

    /**
     * 根据id获取user信息
     * @param id
     * @return
     */
    @GetMapping("/fegin/{id}")
    JSONObject showUserById(@PathVariable("id") int id);

}

@FeignClient中,value配置为要访问的微服务名称,fallbackFactory为回调工厂。

3、Controller代码

package com.zhufeng.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.zhufeng.web.api.ShowUserApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName: RestUserController
 * @Description TODO
 * @author 月夜烛峰
 * @date 2022/8/30 09:55
 */
@Slf4j
@RestController
public class RestUserController {

    @Autowired
    ShowUserApi showUserApi;

    @RequestMapping("/fegin/{id}")
    public JSONObject showUserInfo(@PathVariable("id") int id) {
        log.info("接收到feign请求,id:"+id);
        JSONObject userJson = new JSONObject();
        userJson.put("status", "success");
        userJson.put("name","zhufeng");
        return userJson;
    }

    @RequestMapping("/user/{id}")
    public JSONObject showUserById(@PathVariable("id") int id) {
        log.info("请求参数id:"+id);
        return showUserApi.showUserById(id);
    }

}

4、回调工厂

当访问异常时,回调工厂对返回进行进行特殊处理。

package com.zhufeng.web.fallback;

import com.alibaba.fastjson.JSONObject;
import com.zhufeng.web.api.ShowUserApi;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @ClassName: UserFallbackFactory
 * @Description fegin接口回调工厂类
 * @author 月夜烛峰
 * @date 2022/8/31 16:58
 */
@Slf4j
@Component
public class UserFallbackFactory implements FallbackFactory<ShowUserApi> {
    @Override
    public ShowUserApi create(Throwable throwable) {
        log.error("请求接口报错。。。");
        return new ShowUserApi() {
            @Override
            public JSONObject showUserById(int id) {
                log.info("调用工厂:id="+id);
                JSONObject json = new JSONObject();
                json.put("id", id);
                json.put("status", "error");
                json.put("type", "factory");
                json.put("msg", "no user found...");
                return json;
            }
        };
    }
}

在浏览器中 127.0.0.1:8081/user/1001 访问showUserById方法,该方法调用feign接口访问showUserInfo。

可以正常获取数据,接口访问正常。

注意:

注册中心使用的nacos,需要将zhufengweb-user服务注册到nacos中。

过程参考:《从0到1学SpringCloud——05 注册微服务到nacos

三、文件配置

1、Feign接口日志级别

在Feign中内置了日志级别:

NONE:默认值,不记录任何日志
BASIC:仅记录请求方法、URL、响应状态码以及执行时间
HEADERS:记录 BASIC 级别的基础上,记录请求和响应的 header
FULL:记录请求和响应的 header、body 和元数据

FULL虽然记录信息较全,但实际使用时因资源存储限制,大多使用BASIC。

这里以FULL级别展示有哪些信息

配置项:

#feign接口信息打印
logging.level.com.zhufeng.web.api.ShowUserApi=debug
#全局配置
feign.client.config.default.loggerLevel = full
#也可指定微服务中打印feign信息
#feign.client.config.zhufeng-web-user.loggerLevel=full

运行效果,控制台打印了 ShowUserApi#showUserById 信息:

2022-09-02 11:07:03.811  INFO 18022 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 接收到feign请求,id:1001
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] <--- HTTP/1.1 200 (102ms)
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] connection: keep-alive
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] content-type: application/json
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] date: Fri, 02 Sep 2022 03:07:03 GMT
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] keep-alive: timeout=60
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] transfer-encoding: chunked
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] 
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] {"name":"zhufeng","status":"success"}
2022-09-02 11:07:03.838 DEBUG 18022 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] <--- END HTTP (37-byte body)
2022-09-02 11:07:04.797  INFO 18022 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: zhufeng-web-user.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

2、超时时间

微服务请求通信中,极有可能出现请求超时或着网络不同的情况

# 开启Feign对Hystrix的支持,使回调函数生效
feign.hystrix.enabled=true

# 超时时间可根据不同微服务进行配置,例如仅配置 zhufeng-web-user
# 指定Feign连接提供者的超时时限,5秒
feign.client.config.zhufeng-web-user.connectTimeout=5000
# 指定Feign从请求响应的超时时限,5秒
feign.client.config.zhufeng-web-user.readTimeout=5000

#超时时间全局配置,全局配置只需要指定default即可
#feign.client.config.default.loggerLevel = full
# 指定Feign连接提供者的超时时限,5秒
#feign.client.config.default.connectTimeout=5000
# 指定Feign从请求响应的超时时限,5秒
#feign.client.config.default.readTimeout=5000

配置超时时间后,为验证是否生效,可在请求的接口中设置等待时间大于5秒

对Controller代码进行修改,增加等待时间:

@RequestMapping("/fegin/{id}")
public JSONObject showUserInfo(@PathVariable("id") int id) {
    log.info("接收到feign请求,id:"+id);
    JSONObject userJson = new JSONObject();
    userJson.put("status", "success");
    userJson.put("name","zhufeng");
    try {
        for(int i=9;i>0;i--){
            log.info("请求等待中..."+i);
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        log.error("服务超时,",e);
    }
    return userJson;
}

因为5秒内,没有返回数据,服务超时,返回信息为回调工厂UserFallbackFactory中配置的信息。 

控制台日志信息:

2022-09-02 10:49:47.964  INFO 17734 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 接收到feign请求,id:1001
2022-09-02 10:49:47.988  INFO 17734 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 请求等待中...9
2022-09-02 10:49:48.885 ERROR 17734 --- [ HystrixTimer-1] c.z.web.fallback.UserFallbackFactory     : 请求接口报错。。。
2022-09-02 10:49:48.889  INFO 17734 --- [ HystrixTimer-1] c.z.web.fallback.UserFallbackFactory     : 调用工厂:id=1001
2022-09-02 10:49:48.949  INFO 17734 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: zhufeng-web-user.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2022-09-02 10:49:48.994  INFO 17734 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 请求等待中...8
2022-09-02 10:49:49.999  INFO 17734 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 请求等待中...7
2022-09-02 10:49:51.006  INFO 17734 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 请求等待中...6
2022-09-02 10:49:52.011  INFO 17734 --- [nio-8081-exec-2] c.z.web.controller.RestUserController    : 请求等待中...5
2022-09-02 10:49:52.972 DEBUG 17734 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] <--- ERROR SocketTimeoutException: Read timed out (5098ms)
2022-09-02 10:49:52.973 DEBUG 17734 --- [feng-web-user-1] com.zhufeng.web.api.ShowUserApi          : [ShowUserApi#showUserById] java.net.SocketTimeoutException: Read timed out
	at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:280)
	at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:306)
	at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:347)

四、性能优化

默认情况下Feign不使用线程池,在并发请求较多时,会产生性能问题,可做如下配置:

# 使用httpclient链接池
feign.httpclient.enabled=true
# 连接池中最大连接数,默认值200
feign.httpclient.max-connections=200
# 每个route最大并发连接数 默认值50
feign.httpclient.max-connections-per-route=50

重新启动项目,日志级别设置为debug,控制台打印信息:

2022-09-02 12:14:41.895 DEBUG 18667 --- [feng-web-user-1] o.a.h.client.protocol.RequestAuthCache   : Auth cache not set in the context
2022-09-02 12:14:41.896 DEBUG 18667 --- [feng-web-user-1] h.i.c.PoolingHttpClientConnectionManager : Connection request: [route: {}->http://10.211.55.2:8081][total available: 0; route allocated: 0 of 50; total allocated: 0 of 200]
2022-09-02 12:14:41.898 DEBUG 18667 --- [feng-web-user-1] h.i.c.PoolingHttpClientConnectionManager : Connection leased: [id: 0][route: {}->http://10.211.55.2:8081][total available: 0; route allocated: 1 of 50; total allocated: 1 of 200]
2022-09-02 12:14:41.898 DEBUG 18667 --- [feng-web-user-1] o.a.http.impl.execchain.MainClientExec   : Opening connection {}->http://10.211.55.2:8081

如果打印 PoolingHttpClientConnectionManager 相关信息,则说明配置已生效

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月夜烛峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值