微服务_fegin

Feign服务调用

是客户端组件

ruoyi系统中Log\Auth\User用了远程服务调用,用工厂模式给他的报错加了层工厂类,return错误的时候重写了以下方法。

在ruoyi-common-core模块中引入依赖

        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>

会调用同一url中的其他服务中的接口方法(对应其他服务中的controller),在这里只是映射下路径换个名字。所以不需要实现接口。

  • http调用?
  • 因为是http调用,所有要调用别人负责处理网络请求的controller层。同时在自己这里属于是业务层。

为了方便统一管理,就都在api模块了。其实依赖了api模块,相当于自己有api模块。

被调用方不需要依赖api模块

被调用的几乎什么都不用做

调用匹配机制:url+

@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.FORUM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService

注解上的value是模块名字

请求传参

Get方式传参,使用@PathVariable@RequestParam注解接收请求参数

@GetMapping(value = "/user/info/{username}")
public R<LoginUser> getUserInfo(@PathVariable("username") String username);

@RequestParam(“参数名”)

Post方式传参,使用@RequestBody注解接收请求参数。

@PostMapping("/operlog")
public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog);

反客为主了属于是,原来是参数从url中匹配,现在是调用时传给url,url给远程服务,远程服务再从url取

在openfeign传递参数必须加入注解(在接口声明处),不然会报参数传入过多错误。

跨模块公用的类。多个模块都要用,所以最好声明在专门的模块中,如ruoyi中的api

数组:

/test?ids=21&ids=22

@GetMapping("/test3")
String tests(@RequestParam("ids") String[] ids) 

可以调用方传集合,被调用方用vo中的list接受,类似前端传数据,名字对应就行,会自动映射到vo中的list

ruoyi中接口访问分为两种,一种是由Gateway网关访问进来,一种是内网通过Feign进行内部服务调用。

OpenFeign

Feign本身并不支持Spring MVC的注解,它有一套自己的注解,为了更方便的使用Spring Cloud孵化了OpenFeign。并且支持了Spring MVC的注解,如@RequestMapping@PathVariable等等。
OpenFeign@FeignClient可以解析Spring MVC@RequestMapping注解下的接口,并通过动态代理方式产生实现类,实现类中做负载均衡调用服务。

Feign(NetFlix)---->维护---->SpringCloud OpenFeign

是一个声明式的伪http客户端

简单:写一个接口,加一个注解,调用服务代码。自动完成数据转换

具有可插拔的注解特性(支持SpringMVC注解),可使用Feign注解和JAX-RS注解.

支持可插拔的编码器和解码器,默认集成了Ribbon。

使用

调用方写对应的接口,被调用的干自己原来事情就好,啥也不用做(本来被调用方就是顺便帮忙的,代码复用的,被调用是兼职)

返回值和形参一样就行,方法名不需要一样(因为是靠uri一一对应的,不是靠方法名对应的)

入口类加入注解@EnableDiscoveryClient,consul的注解,此处注册中心用Consul

服务调用方引入OpenFeign的依赖


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

在服务调用方入口类上加注解@EnableFeignClients

被调用方入口类不用加这个注解,除非它同时也是个调用方

一般远程调用的专门写个包,如feignClient

//例子1
@FeignClient("被调用的服务id")	//value
public interface ProductClient{
    
}

//例子2 ruoyi
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{
    /**
     * 通过用户名查询用户信息
     *
     * @param username 用户名
     * @param source 请求来源
     * @return 结果
     */
    @GetMapping("/user/info/{username}")
    public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);

    /**
     * 注册用户信息
     *
     * @param sysUser 用户信息
     * @param source 请求来源
     * @return 结果
     */
    @PostMapping("/user/register")
    public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

调用方直接用这个接口声明成员变量,然后调用接口中的方法。

例, 当auth模块的SysLoginService调用remoteUserService.getUserInfo(username, SecurityConstants.INNER);方法时,调用的其实是system模块里同url的controller里的方法。

api模块相当于一个配置的地方,将可以被远程调用的接口根据url在api模块下映射一下,然后调用api模块中的方法会找到对应的接口

因为服务调用是跨端口的,调用方(auth)要知道被调用方(system)的url

默认轮询负载均衡

响应处理

超时处理

在调用方设置请求被调用方时的超时时间

要求服务一秒内响应,否则报错

修改默认超时设置

feign.client.config.服务id.connectTimeout=5000	#配置指定服务连接超时
feign.client.config.服务id.readTimeout=5000	#配置指定服务等待超时
feign.client.config.default.connectTimeout=5000	#配置所有服务连接超时
feign.client.config.default.readTimeout=5000	#配置所有服务等待超时

ribbon超时设置

Feign的负载均衡底层用的就是Ribbon,所以请求超时其实就只需要配置Ribbon参数。

全局配置

# 请求处理的超时时间
ribbon:
  ReadTimeout: 10000
  ConnectTimeout: 10000

局部配置

# ruoyi-xxxx 为需要调用的服务名称
ruoyi-xxxx:
  ribbon:
    ReadTimeout: 10000
    ConnectTimeout: 10000

日志

在调试时开启详细日志

logging.level.com.包名=debug 

feign为每个客户端提供了日志对象
微服务_fegin_第1张图片

feign.clientl.config.服务id.loggerLevel=full 

代码设置

全局配置

@Bean
public Logger.Level getLog()
{
	return Logger.Level.FULL;
}

局部配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.Logger;

/**
 * Feign 客户端配置
 *
 * @author ruoyi
 */
@Configuration
public class FeignConfiguration
{
    @Bean
    Logger.Level feignLoggerLevel()
    {
        return Logger.Level.FULL;
    }
}

// ====== 在客户端接口指定此配置 ======

/**
 * 用户服务
 * 
 * @author ruoyi
 */
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class, configuration = FeignConfiguration.class)
public interface RemoteUserService
{
} 

Http连接池

两台服务器建立HTTP连接的过程涉及到多个数据包的交换,很消耗时间。采用HTTP连接池可以节约大量的时间提示吞吐量。

FeignHTTP客户端支持3种框架:HttpURLConnectionHttpClientOkHttp

默认是采用java.net.HttpURLConnection,每次请求都会建立、关闭连接,为了性能考虑,可以引入httpclientokhttp作为底层的通信框架。

例如将FeignHTTP客户端工具修改为HttpClient

1、添加依赖


<dependency>
    <groupId>io.github.openfeigngroupId>
    <artifactId>feign-httpclientartifactId>
dependency>

2、全局配置

feign:
  httpclient:
    # 开启httpclient
    enabled: true

请求拦截器

在可以通过实现feign.RequestInterceptor接口在feign执行后进行拦截,对请求头等信息进行修改。

例如项目中利用feign拦截器将本服务的userIduserNameauthentication传递给下游服务

import feign.RequestInterceptor;
import feign.RequestTemplate;

/**
 * feign 请求拦截器
 * 
 */
@Component
public class FeignRequestInterceptor implements RequestInterceptor
{
    @Override
    public void apply(RequestTemplate requestTemplate)
    {

    }
}

你可能感兴趣的:(微服务,java,spring,fegin)