1、Consul服务注册与发现

1、Consul简介

1、简介

  • Consul 是一套开源的分布式服务发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发。
  • 提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。
  • 它具有很多优点。包括:基于 raft 协议,比较简洁;支持健康检查, 同时支持 HTTP 和 DNS 协议支持跨数据中心的 WAN 集群提供图形界面跨平台,支持 Linux、Mac、Windows

    2、作用

    1、服务发现

    提供HTTP和DNS两种发现方式。

    2、健康监测

    支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控

    3、KV存储

    Key、Value的存储方式

    4、多数据中心

    Consul支持多数据中心

    5、可视化Web界面

    3、官网

    https://www.consul.io/downloads

    4、如何使用

    https://www.springcloud.cc/spring-cloud-consul.html

    2、安装并运行Consul

    1、官网安装说明

    https://learn.hashicorp.com/tutorials/consul/get-started-install

    2、这里我们采用docker 来运行consul

  • 运行1.6.1的版本

    1. docker run -it --name consul8500 -p 8500:8500 consul:1.6.1
  • 之后访问

  • 配置pom.xml ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    

      <artifactId>cloud2020</artifactId>
      <groupId>com.daijunyi</groupId>
      <version>1.0-SNAPSHOT</version>
    

    4.0.0 cloud-providerconsul-payment8006 org.springframework.cloud spring-cloud-starter-consul-discovery org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test


- 配置yaml
```yaml
###consul服务端口号
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
  ####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}

2、主启动类

package com.daijunyi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsulMainApplication8006 {
    public static void main(String[] args) {
        SpringApplication.run(ConsulMainApplication8006.class,args);
    }
}

3、controller业务类

package com.daijunyi.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/consul")
    public String paymentInfo()
    {
        return "springcloud with consul: "+serverPort+"\t\t"+ UUID.randomUUID ().toString();
    }
}

4、测试

  • 测试consul是否注册成功

访问localhost:8500
image.png

  • 测试业务类

http://localhost:8006/payment/consul

4、服务消费者

1、创建cloud-consumerconsul-order80

  • 修改pom.xml ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    

      <artifactId>cloud2020</artifactId>
      <groupId>com.daijunyi</groupId>
      <version>1.0-SNAPSHOT</version>
    

    4.0.0 cloud-consumerconsul-order80 org.springframework.cloud spring-cloud-starter-consul-discovery org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test


- 修改yaml
```yaml
sserver:
  port: 80

spring:
  application:
    name: cloud-consumer-order
  ####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}

2、主启动类

package com.daijunyi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerConsulMainApplication80 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerConsulMainApplication80.class,args);
    }
}

3、创建配置类

package com.daijunyi.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

4、controller

package com.daijunyi.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
public class PaymentController {

    private static final String serverUrl = "http://consul-provider-payment";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/consul")
    public String paymentConsul(){
        String forObject = restTemplate.getForObject(serverUrl + "/payment/consul", String.class);
        return forObject;
    }

}

5、测试

  • consul的服务注册
  • 业务测试

  • C:Consistency(强一致性)

  • A:Availability(可用性)
  • P:Partition tolerance(分区容错性)
  • CAP理论关注粒度是数据,而不是整体系统设计的策略

    2、经典CAP图

  • 最多只能同时较好的满足两个。

  • CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求, 因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三大类:
    • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
    • CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
    • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

1、AP架构

  • Eureka

当网络分区出现后,为了保证可用性,系统B 可以返回旧值,保证系统的可用性。
结论:违背了一致性C的要求,只满足可用性和分区容错,即AP
image.png

2、CP架构

  • consul
  • zookeeper

当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP
image.png

2、Ribbon负载均衡服务调用

1、简介

1、概述

  • Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。
  • 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

    2、官网资料

  • 文档地址

https://github.com/Netflix/ribbon/wiki/Getting-Started

  • 已进入维护不升级了
  • 暂时没有替代产物

https://github.com/Netflix/ribbon
image.png

3、作用

  • LB(负载均衡)
  • 负载均衡+RestTemplate调用

    1、LB负载均衡(Load Balance)是什么

  • 简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。

  • 常见的负载均衡有软件Nginx,LVS,硬件 F5等。

    2、Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别

  • Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。

  • Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。

    3、集中式LB

  • 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;

    4、进程内LB

  • 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。

  • Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

    2、Ribbon负载均衡演示

    1、架构说明

    image.png

  • Ribbon在工作时分成两步

    • 第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
    • 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。 其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。
  • 总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

    2、之前Pom文件中并没有引入,但可以使用的原因

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        <version>2.2.1.RELEASE</version>
        <scope>compile</scope>
      </dependency>
    
  • Eureka帮引入了

image.png

  • consul也引入了

image.png

  • zookeeper也引入了

image.png

3、RestTemplate的使用

1、官网

https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

  • 使用entities的方式可以获取到更加相信的请求头等信息 ```java @GetMapping(“/consumer/payment/entities/get/{id}”) public CommonResult getPaymentEntities(@PathVariable Long id){ ResponseEntity forEntity = restTemplate.getForEntity(PAYMENT_URL + “/payment/get/“ + id, CommonResult.class); if (forEntity.getStatusCode().is2xxSuccessful()){
      return forEntity.getBody();
    
    }else{
      return new CommonResult<>(444,"发生了内部错误");
    
    } }

@PostMapping(“/consumer/payment/entities/create”) public CommonResult createEntities(@RequestBody Payment payment) { log.info(payment.toString()); ResponseEntity commonResultResponseEntity = restTemplate.postForEntity(PAYMENT_URL + “/payment/create”, payment, CommonResult.class); if (commonResultResponseEntity.getStatusCode().is2xxSuccessful()){ return commonResultResponseEntity.getBody(); }else{ return new CommonResult<>(444,”创建失败”); } }

<a name="c9leF"></a>
## 3、**Ribbon核心组件IRule**

- IRule:根据特定算法中从服务列表中选取一个要访问的服务
- ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630394878578-f80a0052-b171-468a-996f-378be9c41f26.png#clientId=u89a670cd-b5db-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=234&id=uafe985b8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=468&originWidth=1216&originalType=binary&ratio=1&rotation=0&showTitle=false&size=61970&status=done&style=none&taskId=u2e075350-2987-46a8-9dc9-fff6edb75fe&title=&width=608)
<a name="ROeAy"></a>
### 1、常用的负载均衡算法类

- com.netflix.loadbalancer.RoundRobinRule
   - 轮询
- com.netflix.loadbalancer.RandomRule
   - 随机
- com.netflix.loadbalancer.RetryRule
   - 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
- WeightedResponseTimeRule
   - 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
- BestAvailableRule
   - 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
- AvailabilityFilteringRule
   - 先过滤掉故障实例,再选择并发较小的实例
- ZoneAvoidanceRule
   - 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
<a name="ccanN"></a>
### 2、如何替换

- cloud-consumer-order80
<a name="I8ejt"></a>
#### 1、注意配置细节,官方文档明确给出了警告:  
这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下, <br />否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。 
<a name="aW5E7"></a>
#### 2、新建package
com.myrule
<a name="Hee31"></a>
#### 3、com.myrule下新建类RuleConfig
```java
package com.myrule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RuleConfig {

    @Bean
    public IRule iRule(){
        return new RandomRule();
    }
}

3、修改主配置类

  • 添加@RibbonClient(name = “CLOUD-PAYMENT-SERVICE”,configuration = {RuleConfig.class})
  • 表示对CLOUD-PAYMENT-SERVICE这个服务进行随机规则的负载均衡配置 ```java package com.daijunyi;

import com.myrule.RuleConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication @EnableEurekaClient @RibbonClient(name = “CLOUD-PAYMENT-SERVICE”,configuration = {RuleConfig.class}) public class MainConsumerOrderAppliction80 {

public static void main(String[] args) {
    SpringApplication.run(MainConsumerOrderAppliction80.class);
}

}

<a name="f0YVq"></a>
#### 4、测试
[http://localhost/consumer/payment/entities/get/1](http://localhost/consumer/payment/entities/get/1)<br />返回值就是会随机一台服务器访问
<a name="qPb4L"></a>
## 4、**Ribbon负载均衡算法**
<a name="vhzPN"></a>
### 1、原理
负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标  ,每次服务重启动后rest接口计数从1开始。 <br />List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); <br />如:   List [0]  instances  = 127.0.0.1:8002 <br />List [1]  instances  = 127.0.0.1:8001 <br /> 8001+ 8002 组合成为集群,它们共计2台机器,集群总数为2, 按照轮询算法原理: <br />当总请求数为1时: 1 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001 <br />当总请求数位2时: 2 % 2 =0 对应下标位置为0 ,则获得服务地址127.0.0.1:8002 <br />当总请求数位3时: 3 % 2 =1 对应下标位置为1 ,则获得服务地址为127.0.0.1:8001 <br />当总请求数位4时: 4 % 2 =0 对应下标位置为0 ,则获得服务地址127.0.0.1:8002 <br />如此类推...... 
<a name="aHq0N"></a>
### 3、手写模拟一个负载均衡
<a name="UHtLk"></a>
#### 1、8001和8002项目添加一个请求地址
```java
    @GetMapping("/lb/port")
    public Object getLBPort(){
        return this.serverPort;
    }

2、添加lb相关的代码

  • LoadBalancer ```java package com.daijunyi.lb;

import org.springframework.cloud.client.ServiceInstance;

import java.util.List;

public interface LoadBalancer {

public ServiceInstance chooseService(List<ServiceInstance> serviceInstances);

}


- RoundRobinLB
```java
package com.daijunyi.lb;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class RoundRobinLB implements LoadBalancer{

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getIncrement(){
        int current;
        int next;
        do {
            current = atomicInteger.get();
            next = current > Integer.MAX_VALUE ? 0 : current+1;
        } while (!atomicInteger.compareAndSet(current,next));
        log.info("当前值:"+next);
        return next;
    }

    public ServiceInstance chooseService(List<ServiceInstance> serviceInstances) {
        if (serviceInstances == null || serviceInstances.size() == 0){
            return null;
        }
        int index = getIncrement() % serviceInstances.size();
        ServiceInstance instance = serviceInstances.get(index);
        return instance;
    }
}

3、修改配置类

package com.daijunyi.config;

import com.daijunyi.lb.RoundRobinLB;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {

    @Bean
//    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    public RoundRobinLB roundRobinLB(){
        return new RoundRobinLB();
    }
}

4、写业务代码

package com.daijunyi.controller;

import com.daijunyi.entities.CommonResult;
import com.daijunyi.entities.Payment;
import com.daijunyi.lb.RoundRobinLB;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@Slf4j
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RoundRobinLB roundRobinLB;


    @GetMapping("/consumer/lb/port")
    public String getLBPort(){
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if (instances == null || instances.size() == 0){
            return null;
        }

        ServiceInstance instance = roundRobinLB.chooseService(instances);
        String url = instance.getUri() + "/lb/port";
        log.info(url);
        String forObject = restTemplate.getForObject(url, String.class);
        return forObject;
    }

}

5、测试

访问http://localhost/consumer/lb/port
会发现打印不同的端口号


3、OpenFeign服务接口调用

1、概述

1、OpenFeign是什么

  • 官网解释:

https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign

  • Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。
  • 它的使用方法是定义一个服务接口然后在上面添加注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡

    2、作用

    1、Feign能干什么

    Feign旨在使编写Java Http客户端变得更容易。
    前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。

    2、Feign集成了Ribbon

    利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

    3、Feign和OpenFeign两者区别

    | Feign | OpenFeign | | —- | —- | | Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
    Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务 | OpenFeign是Spring Cloud 在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 | | ```xml org.springframework.cloud spring-cloud-starter- feign
    | ```xml
    <dependency > 
    <groupId > org.springframework.cloud </groupId > 
    <artifactId > spring-cloud-starter- openfeign </artifactId > 
    </dependency >
    
    |

2、OpenFeign使用步骤

  • 接口+注解
    • 微服务调用接口+@FeignClient
  • OpenFeign默认是使用的轮询的负载均衡
  • 所以如果想要修改规则就以上面的Ribbon修改规则的算法一样配置即可
    • 提示:在主启动类中使用@RibbonClient进行配置

1、cloud-consumer-feign-order80

  • 修改pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <parent>
          <artifactId>cloud2020</artifactId>
          <groupId>com.daijunyi</groupId>
          <version>1.0-SNAPSHOT</version>
      </parent>
      <modelVersion>4.0.0</modelVersion>
    
      <artifactId>cloud-consumer-feign-order80</artifactId>
    
      <dependencies>
          <!--openfeign-->
          <dependency >
              <groupId >org.springframework.cloud</groupId >
              <artifactId >spring-cloud-starter-openfeign</artifactId >
          </dependency >
          <!--eureka client-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
          </dependency>
          <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
          <dependency>
              <groupId>com.daijunyi</groupId>
              <artifactId>cloud-api-commons</artifactId>
              <version>${project.version}</version>
          </dependency>
          <!--web-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
          <!--一般基础通用配置-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
      </dependencies>
    </project>
    

    2、修改yaml

    ```yaml server: port: 80

eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

<a name="McCuT"></a>
### 3、主启动类

- 开启FeignClient功能
```java
package com.daijunyi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class ConsumerFeignOrderMainApplication80 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignOrderMainApplication80.class,args);
    }
}

4、测试

  • http://localhost/consumer/payment/get/1

    3、OpenFeign超时控制

  • 可以在客户端配置读取超时时间,默认是1秒超时

    #设置feign客户端超时时间(OpenFeign默认支持ribbon)
    ribbon:
    #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
    ReadTimeout:  5000
    #指的是建立连接后从服务器读取到可用资源所用的时间
    ConnectTimeout:  5000
    

    4、OpenFeign日志打印功能

    1、简介

    Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。
    说白了就是对Feign接口的调用情况进行监控和输出

    2、日志级别

  • NONE

    • 默认的,不显示任何日志;
  • BASIC
    • 仅记录请求方法、URL、响应状态码及执行时间;
  • HEADERS
    • 除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
  • FULL
    • 除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

      3、配置日志Bean

      ```java package com.daijunyi.config;

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

@Configuration public class FeignConfig {

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

}

<a name="u2t9c"></a>
### 4、配置yaml文件

- YML文件里需要开启日志的Feign客户端
- 指定哪个配置接口文件打印什么日志
```yaml
logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.daijunyi.service.PaymentFeignService:  debug
2021-09-01 00:35:29.791 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] ---> GET http://CLOUD-PAYMENT-SERVICE/payment/get/1 HTTP/1.1
2021-09-01 00:35:29.791 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] ---> END HTTP (0-byte body)
2021-09-01 00:35:29.803 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] <--- HTTP/1.1 200 (12ms)
2021-09-01 00:35:29.803 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] connection: keep-alive
2021-09-01 00:35:29.803 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] content-type: application/json
2021-09-01 00:35:29.803 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] date: Tue, 31 Aug 2021 16:35:29 GMT
2021-09-01 00:35:29.803 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] keep-alive: timeout=60
2021-09-01 00:35:29.804 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] transfer-encoding: chunked
2021-09-01 00:35:29.804 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] 
2021-09-01 00:35:29.804 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] {"code":200,"message":"查询成功,serverPort:8002","data":{"id":1,"serial":"红领巾"}}
2021-09-01 00:35:29.804 DEBUG 30580 --- [p-nio-80-exec-2] c.daijunyi.service.PaymentFeignService   : [PaymentFeignService#getPaymentById] <--- END HTTP (90-byte body)