OpenFeign使用

OpenFeign

一、简单使用

1.导入依赖

     <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2.配置开启

主启动类添加@EnableFeignClients注解

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class CloudalibabaConsumerNacosOrder83Application {

    public static void main(String[] args) {
        SpringApplication.run(CloudalibabaConsumerNacosOrder83Application.class, args);
        System.out.println("启动成功");
    }

}

3.写OpenFeign接口

import com.wzy.springcloud.alibaba.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;

//value值为要调用的目标微服务名
@FeignClient(value="nacos-payment-provider")
public interface FeignTool {

    /**
     * get请求参数传递,路径参数
     * */
    @GetMapping(value = "/payment/nacos/path/{id}/{name}")
    String getPath(@PathVariable("id") Integer id,@PathVariable("name")String name);

}

4.写controller调用

FeignTool为上面的OpenFeign接口

@RestController
@Slf4j
@RequestMapping("consumer")
public class OrderNacosController {

    @Autowired
    private FeignTool feighTool;

    
    //get请求参数传递,rest路径参数
    @GetMapping(value = "/payment/nacos/path/{id}/{name}")
    String getPath(@PathVariable("id") Integer id,@PathVariable("name")String name){
        return feighTool.getPath(id,name);
    }
}

5.被调用服务

写被调用服务接收的controller

@RestController
public class PaymentController {

    @GetMapping(value = "/payment/nacos/path/{id}/{name}")
    public String getPath(@PathVariable("id") Integer id,@PathVariable("name")String name) {
        return "id:" + id+","+"name:"+name;
    }
    
}

6.日志级别

openfeign有4种日志级别,从低到高:

NONE:默认级别,不显示日志

BASIC:仅记录请求方法、URL、响应状态及执行时间

HEADERS:除了BASIC中定义的信息之外,还有请求和响应头信息

FULL:除了HEADERS中定义的信息之外,还有请求和响应正文及元数据信息

配置类:

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

/**
 * openFeign有四种日志级别
 * NONE
 * BASIC
 * HEADERS
 * FULL
 *
 * */
@Configuration
public class openFeignLogger {
    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

yml配置:

#日志记录器(Logger)的行为是分等级的:
#分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。
#Log4j建议只使用四个级别,优先级 从高到低分别是 ERROR、WARN、INFO、DEBUG。
logging:
  level:
    #openFeign日志以什么级别监控哪个接口
    com.wzy.springcloud.alibaba.service.FeignTool: debug

BASIC配置及日志打印效果:

image-20221013091305823

image-20221013091618505

HEADERS配置及日志打印效果:

image-20221013091702108

image-20221013091959343

FULL配置及日志打印效果:

image-20221013095343025

image-20221013095319089

日志名词解析

Keep-alive:

Keep-alive使客户端到服务器端的连接持续有效,当出现对服务器的后续请求时,Keep-alive功能避免了建立或者重新建立连接。现在的大多数Web服务器都支持Keep-alive。

Keep-alive:timeout=5,max=100
意思是说:过期时间5秒,max是最多100次请求,强制断掉连接,也就是在timeout时间内每来一个新的请求,max会自动减1,直到为0,强制断掉连接。

Transfer-Encoding:chunked:

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

通常,HTTP应答消息中发送的数据是整个发送的,Content-Length消息头字段表示数据的长度。数据的长度很重要,因为客户端需要知道哪里是应答消息的结束,以及后续应答消息的开始。然而,使用分块传输编码,数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小。通常数据块的大小是一致的,但也不总是这种情况。

7.服务降级

yaml配置文件:

feign:
  hystrix:
    enabled: true

接口代码,fallback为降级调用类,即接口调用报错使用此类返回

import com.service.impl.PaymentFallbackServiceImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
//fallback为降级调用类,即接口调用报错使用该类返回信息
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackServiceImpl.class)
public interface PaymentHystrixService {

    @GetMapping("/pay/hy/ok/{id}")
    String paymentInfoOK(@PathVariable("id") Integer id);

    @GetMapping("/pay/hy/to/{id}")
    String paymentInfoTimeOut(@PathVariable("id") Integer id);
}

降级类:

import com.service.PaymentHystrixService;
import org.springframework.stereotype.Component;

public class PaymentFallbackServiceImpl implements PaymentHystrixService {

    @Override
    public String paymentInfoOK(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
    }

    @Override
    public String paymentInfoTimeOut(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
    }

}

8.openfeign通讯优化,GZIP压缩

GZIP简介

gzip介绍:

gzip是一种数据格式,采用用deflate算法压缩数据;gzip是一种流行的数据压缩算法,应用十分广泛,尤其是在Linux平台。

gzip能力:

当Gzip压缩到一个纯文本数据时,效果是非常明显的,大约可以减少70%以上的数据大小。

gzip作用:

网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。网页加载速度加快的好处不言而喻,除了节省流量,改善用户的浏览体验外,另一个潜在的好处是Gzip与搜索引擎的抓取工具有着更好的关系。例如 Google就可以通过直接读取gzip文件来比普通手工抓取更快地检索网页。

HTTP协议中关于压缩传输的规定(原理)

image-20221012165151482

第一:

客户端向服务器请求头中带有:Accept-Encoding:gzip, deflate 字段,向服务器表示,客户端支持的压缩格式(gzip或者deflate),如果不发送该消息头,服务器是不会压缩的。

第二:

服务端在收到请求之后,如果发现请求头中含有Accept-Encoding字段,并且支持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带Content-Encoding:gzip消息头,表示响应报文是根据该格式压缩过的。

第三:

客户端接收到响应之后,先判断是否有Content-Encoding消息头,如果有,按该格式解压报文。否则按正常报文处理。

在Feign技术中应用GZIP压缩

image-20221012165341606

只配置Feign请求-应答的GZIP压缩

在交互数据量级不够的时候,看不到压缩内容。这里只开启Feign请求-应答过程中的GZIP,也就是浏览器-Application Client之间的请求应答不开启GZIP压缩。在全局配置文件中,使用下述配置来实现Feign请求-应答的GZIP压缩:

feign:
  compression:
    request:
      enabled: true //开启请求压缩
      mime-types: text/xml,application/xml,application/json
      min-request-size: 1024 //设置请求大小,1024kb以上开始压缩
    response:
      enabled: true //响应压缩
      useGzipDecoder: true //响应解码

9.超时时间配置

不配置默认超过1秒调用就会超时

feign:
  hystrix:
    enabled: false #关闭降级
  client:
    config:
      #提供方的服务名,为default时则是通用调用设置
      seata-storage-service:
        #指的是建立连接所用的时间,适用于网络正常的情况下,两端连接所用的时间 毫秒
        connectTimeout: 5000
        #指的是建立连接后从服务器读取到可用资源所用的时间 毫秒
        readTimeout: 5000

二、参数调用示例

1.get请求

路径参数

调用者controller代码

image-20221012161543844

OpenFeign接口

@FeignClient(value="nacos-payment-provider")
public interface FeignTool {

    @GetMapping(value = "/payment/nacos/path/{id}/{name}")
    String getPath(@PathVariable("id") Integer id,@PathVariable("name")String name);
    
}

被调用服务controller

@GetMapping(value = "/payment/nacos/path/{id}/{name}")
public String getPath(@PathVariable("id") Integer id,@PathVariable("name")String name) {
	return "id:" + id+","+"name:"+name;
}

基本类型参数

调用者controller代码

@GetMapping("/payment/nacos/nfp")
    public String nfp(){
        return feighTool.normalFormParam("钢铁侠",33);
    }

OpenFeign接口

/**
 * 表单类型参数传递,基本类型
* */
@GetMapping("/payment/nacos/nfp") //即使与服务方法的参数名一致,也必须有name = ""
String normalFormParam(@RequestParam(name = "name") String name, @RequestParam(name = "age") Integer age);

被调用服务controller

@GetMapping("/payment/nacos/nfp")
String normalFormParam(String name, Integer age){
	return "name:"+name+","+"age"+age;
}

集合类型参数

调用者controller代码

@GetMapping("/payment/nacos/hash")
HashMap<String,String> hashParam(){
        HashMap<String,String> h = new  HashMap();
        h.put("1","one");h.put("2","two");h.put("3","three");
        return feighTool.hashParam(h);
}    

OpenFeign接口

@GetMapping("/payment/nacos/hash")
HashMap<String,String>  hashParam(@SpringQueryMap HashMap<String,String> h);

被调用服务controller

@GetMapping("/payment/nacos/hash")
HashMap<String,String>  hashParam(@RequestParam HashMap<String,String> h){
        System.out.println(h);
        return h;
}    

自定义类型参数,User为自定义类型

调用者controller代码

@GetMapping("/payment/nacos/user")
User userParam(){
        User u = new User();
        u.setAge(26);
        u.setName("wangziyu");
        return feighTool.userParam(u);
}   

OpenFeign接口

@GetMapping("/payment/nacos/user")
User userParam(@SpringQueryMap User u);

被调用服务controller

@GetMapping("/payment/nacos/user")
User userParam(User u){
        System.out.println(u);
        return u;
}    

2.post请求

@RequestBody,基本类型

调用者controller代码

@GetMapping("/payment/nacos/str")
public String strBody(){
	return feighTool.strBodyParam("success");
}    

OpenFeign接口

@PostMapping("/payment/nacos/str")
String strBodyParam(@RequestBody String s);//此处可以不加@RequestBody,不加注解默认就是@RequestBody

被调用服务controller

@PostMapping("/payment/nacos/str")
String strBodyParam(@RequestBody String s){
	return s;
}

@RequestBody,集合类型

调用者controller代码

//HashMap
@GetMapping("/payment/nacos/map")
public HashMap<String,String> mapBody(){
    
	HashMap<String,String> h = new  HashMap();
	h.put("1","one");h.put("2","two");h.put("3","three");
	return feighTool.mapBodyParam(h);
    
}    

OpenFeign接口

@PostMapping("/payment/nacos/map")
HashMap<String,String> mapBodyParam(@RequestBody HashMap<String,String> h);//此处可以不加@RequestBody,不加注解默认就是@RequestBody

被调用服务controller

@PostMapping("/payment/nacos/map")
HashMap<String,String> mapBodyParam(@RequestBody HashMap<String,String> h){
	return h;
}

@RequestBody,自定义类型

调用者controller代码

 //自定义Entity类型
    @GetMapping("/payment/nacos/rb")
    public User restBody(){
        User u = new User();
        u.setAge(22);
        u.setName("wzy");
        return feighTool.reqBodyParam(u);
    }

OpenFeign接口

@PostMapping("/payment/nacos/rb")
User reqBodyParam(@RequestBody User u); //此处可以不加@RequestBody,不加注解默认就是@RequestBody

被调用服务controller

@PostMapping("/payment/nacos/rb")
User reqBodyParam(@RequestBody User u){
	System.out.println(u);
	return u;
}

三、负载均衡

旧版OpenFeign集成了Ribbon,可使用如下配置:

@Configuration
public class FeignConfiguration {
    /**
     * 配置随机的负载均衡策略
     * 特点:对所有的服务都生效
     */
    @Bean
    public IRule loadBalancedRule() {
        return new RandomRule();
    }
}

并可以关闭ribbon的负载均衡:

spring:
  application:
    name: consumer-name
  cloud:
    loadbalancer:
      # 关闭Ribbon的负载均衡器
      ribbon:
        enabled: false

新版springCloud已不再集成Ribbon,需要使用spring自带的loadbalancer,默认轮询

1.引入pom

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

2.写一个自定义的负载均衡配置类

spring自带的loadbalancer只有两种策略,随机策略RandomLoadBalancer 和 轮询策略RoundRobinLoadBalancer,可以自定义策略

特别注意此配置类不要加@Configuration

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

public class CustomLoadBalancerConfiguration {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory){
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);

        /**随机策略负载均衡*/
        return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);

        /**轮询策略负载均衡*/
        //return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);
    }

}

3.主启动类配置开启

OpenFeign要调用哪个服务,就将哪个服务的名字作为name的值

image-20221013140428121

//单项指定
@LoadBalancerClient(name = "nacos-payment-provider",configuration = CustomLoadBalancerConfiguration.class)

//多项指定
@LoadBalancerClients(
        value = {
                @LoadBalancerClient(name = "nacos-payment-provider",configuration = CustomLoadBalancerConfiguration.class),
                @LoadBalancerClient(name = "nacos-payment-provider",configuration = CustomLoadBalancerConfiguration.class),
        },defaultConfiguration = CustomLoadBalancerConfiguration.class
)

4.单配置开启

@FeignClient(value = "CONSUL-TEST")
@Component
@LoadBalancerClient(name = "CONSUL-TEST",configuration = LoadBalancedConfig.class)
public interface FeignService {

    @LoadBalanced
    @GetMapping("/consul/hello")
    String sayHello();

    @GetMapping("/consul/hello")
    String sayHello2();
}

四、注解参数

@FeignClient 注解是 Spring Cloud OpenFeign 的核心部分,用于声明一个远程 HTTP 服务的客户端接口。下面是一些常用的参数和它们的功能:

  1. namevalue

    • 必需的。这是客户端的名称,用于创建 Ribbon 负载均衡器(如果使用的话)。通常,这也会被用作服务发现中的服务ID。
    @FeignClient(name = "billing-service")
    
  2. url

    • 可选的。用于指定请求的基础 URL。如果指定了此项,Feign 将直接指向该 URL,而忽略服务发现。如果同时指定了 nameurlurl 可以用于开发或测试环境,而 name 则用于通过服务发现找到服务。
    @FeignClient(name = "billing-service", url = "https://api.billing.example.com")
    
  3. contextId

    • 可选的。如果您定义了多个同名的 FeignClient,可以用 contextId 来区分不同的实例。每个上下文ID代表一个独立的Feign客户端配置。
    @FeignClient(contextId = "billingClient", name = "billing-service")
    
  4. configuration

    • 可选的。用于指定一个或多个配置类,这些类可以包含Feign的配置信息,如编码器、解码器、拦截器等。
    @FeignClient(name = "billing-service", configuration = CustomFeignConfig.class)
    
  5. fallback

    • 可选的。用于定义一个类,该类实现了@FeignClient接口,并处理回退逻辑,如在远程服务调用失败时返回默认值或进行其他操作。
    @FeignClient(name = "billing-service", fallback = BillingServiceFallback.class)
    
  6. fallbackFactory

    • 可选的。用于定义一个工厂类,该工厂类实现FallbackFactory<T>接口,用于创建 fallback 实例。这个参数常用于需要访问导致回退的具体原因(比如异常)时。
    @FeignClient(name = "billing-service", fallbackFactory = BillingServiceFallbackFactory.class)
    
  7. path

    • 可选的。定义所有请求的基本路径。这个基路径会被添加到@FeignClient接口中定义的每一个@RequestMapping路径前面。
    @FeignClient(name = "billing-service", path = "/api")
    
  8. decode404

    • 可选的。如果设置为 true,Feign 将会把 404 响应解码成数据而不是抛出 FeignException
    @FeignClient(name = "billing-service", decode404 = true)
    
  9. primary

    • 可选的。指示这个客户端是否是主要的。这可以解决自动装配时的冲突。
    @FeignClient(name = "billing-service", primary = true)
    

这些参数可以帮助你定制化@FeignClient的使用,使其适应不同的场景和需求。

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenFeign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加容易。通过使用OpenFeign,我们可以定义一个接口用于调用远程Web服务,然后在运行时生成一个实现该接口的代理类。 以下是使用OpenFeign的步骤: 1. 添加依赖 在Maven项目中,我们需要添加以下依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` 2. 创建Feign客户端接口 定义一个接口,用于调用远程Web服务。该接口通常会使用Spring MVC注解来定义请求路径、请求参数等信息。 ```java @FeignClient(name = "service-name") public interface MyFeignClient { @RequestMapping(value = "/api/resource", method = RequestMethod.GET) Resource getResource(@RequestParam("id") Long id); } ``` 其中,@FeignClient注解用于定义Feign客户端的名称,name属性指定了远程服务的名称。@RequestMapping注解则用于定义请求路径和请求方法。 3. 注入Feign客户端 在需要调用远程服务的地方,我们可以通过@Autowired注解来注入Feign客户端。 ```java @RestController public class MyController { @Autowired private MyFeignClient myFeignClient; @GetMapping("/resource/{id}") public Resource getResource(@PathVariable Long id) { return myFeignClient.getResource(id); } } ``` 这里,我们将Feign客户端注入到了控制器中,在控制器中调用了getResource方法。 4. 配置Feign客户端 我们可以通过配置文件来配置Feign客户端的行为。例如,我们可以配置连接超时时间、读取超时时间等。 ```yaml feign: client: config: default: connectTimeout: 5000 readTimeout: 5000 ``` 这里,我们将连接超时时间和读取超时时间都设置为了5秒。 以上就是使用OpenFeign的基本步骤,它使得调用远程Web服务变得更加容易。同时,OpenFeign还提供了很多高级特性,例如请求拦截器、响应拦截器等,可以帮助我们更好地管理Web服务客户端。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值