2020周陽SpringCloud完整版筆記--一


微服務架構入門

微服務 的概念最早產生於Martin Fowler在2014年的一篇論文中。

微服務架構是一種架構模式,他提倡將單一應用程序划分成一組小的服務,服務與服務之間互相協調、相互配合,為用戶提供最終價值。每個服務運行在獨立的進程中,服務與服務之間采用輕量級的通信機制相互合作(通常是基於HTTP協議的Restful API)。每個服務圍繞具體業務進行構建,並且能夠被獨立的部署到生產環境、類生產環境等。另外,應當盡量避免同一的、集中式的服務管理機制,對具有的一個服務而言,應當根據業務上下文,選擇合適的語言、工具對其進行構建。

Cloud組件停更

被動修復bug,停更不停用,不再github上接收新的合並請求,不再發布新的版本。

cloud升級

RestTemplate提供了多種邊界訪問遠程HTTP服務的方法,是一種簡單便捷的訪問restful服務模板類,是Spring提供的用於訪問Rest服務的客戶端模板工具集。

(URL,requestMap,ResponseBean.class)這三個參數分別代表REST請求地址,請求參數,HTTP響應轉換的對象類型。

服務注冊中心

Eureka服務注冊中心

什么是服務治理

SpringCloud封裝了Netflix公司開發的Eureka模塊來實現服務治理。

在傳統的RPC遠程調用框架中,管理每個服務於服務之間依賴關系比較復雜,管理比較復雜,所以需要使用服務治理來管理服務與服務之間的依賴關系,可以實現服務調用、負載均衡、容錯等,實現服務發現與注冊。

服務注冊與發現

Eureka采用來CS的設計架構,Eureka Server作為服務注冊功能的服務器,他是服務注冊中心。而系統中的其他微服務,使用Eureka客戶端連接到Eureka Server並維持心跳鏈接。這樣系統的維護人員可以通過Eureka Server來監控系統中各個微服務是否正常運行。

在服務注冊與發現中,有一個注冊中心,當服務器啟動的時候,會把當前自己服務器的信息,比如服務地址,通訊地址等以別名的方式注冊到注冊中心中,另一方(其實也就是消費者或者服務提供者),以別名的方式去注冊中心上獲取實際的服務通信地址,然后在實現本地RPC調用。

RPC遠程調用框架的思想在於:使用注冊中心管理服務與服務之間的依賴關系。在任何RPC遠程框架中都會有一個注冊中心。

Eureka Server和Eureka Client

Eureka Server提供服務注冊

各個微服務節點通過配置啟動后,會在Eureka Server中進行注冊,這樣Eureka Server中的服務注冊表中將會存儲所有可用的節點信息,服務節點信息可以在界面中直觀看到。

Eureka Client通過注冊中心進行訪問

這個客戶端是用來簡化Eureka Server的交互,客戶端同時具備一個內置的,使用輪詢負載算法的負載均衡器。在應用啟動后,將會向Eureka Server發送心跳(默認是30s一次),如果Serve在多個心跳周期內(默認90s)沒有接收到某個節點的心跳,那就會被Server除名(從服務注冊表中將節點移除)。

Eureka架構圖與Dubbo對比

img

img

Eureka Server模塊

1、創建模塊

2、導入依賴

<?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>org.xzq.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.xzq.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--boot web actuator-->
        <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>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

</project>

3、編寫配置文件

​ application.yml

server:
  port: 7001
eureka:
  instance:
    hostname: localhost # eureka服務端實例名稱
  client:
    register-with-eureka: false # 不向注冊中心注冊自己
    fetch-registry: false # 表示自己就是注冊中心,不必檢索其他服務
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 設置與 Eureka Server 交互的地址,可用來查詢注冊的服務

4、創建主類

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

5、啟動server,訪問http://localhost:7001

image-20200902180220370

Eureka集群原理

先啟動Eureka注冊中心,啟動服務提供者,支付服務啟動后會把自身信息以別名的方式注冊進Eureka,消費者order服務在需要調用接口時,使用服務別名去注冊中心獲取實際的遠程調用地址,消費者獲取調用地址后,底層使用的是HTPPClient技術實現遠程調用,消費者獲得服務地址后會魂村到本地JVM內存中,默認每隔30s更新一次服務調用地址。

要實現RPC遠程調用服務最核心的是高可用,但是如何實現高可用?

方法:搭建注冊中心集群,實現負載均衡+故障容錯。

服務注冊中心搭建集群,集群中的所有服務都相互注冊,例如server7001,server7002,7002的eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka,而7001中的Eureka配置是eureka.client.service-url.defaultZone=http://eureka7002.com:7002/eureka。在主啟動類上添加@EnableEurekaServer注解,先啟動這些注冊中心服務,再啟動服務提供者,最后啟動消費者。

服務發現Discovery

@RequestMapping("/payment")
@RestController
@Slf4j
public class PaymentController {
    @Autowired
    private PaymentService paymentService;
    @Value("${server.port}")
    private String serverPort;
    @Resource
    private DiscoveryClient discoClient;
    
    @GetMapping("/discover")
    public Object discovery(){
        List<String> services = discoClient.getServices();
        for (String service : services) {
            log.info("service===="+service);
        }
        List<ServiceInstance> instances =  discoClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info(instance.getInstanceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
        }
        return this.discoClient;

    }
}

在主啟動類上添加@EnableDiscoveryClient注解

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

通過瀏覽器訪問localhost:8001/payment/discover

image-20200903213504777

Eureka的自我保護

所謂的保護模式就是用於一組客戶端和Eureka Server之間存在網絡分區場景下的保護。一旦進入保護模式,Eureka Server將會嘗試保護其服務注冊表中的信息,不再刪除服務注冊表中的數據,也就是不會注銷任何微服務。

如果在Eureka Server的首頁看到以下這段提示,則說明Eureka進入了保護模式:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

image-20200903214526701

一句話:在某時刻一個微服務不可用,Eureka不會立刻清理,依舊會對改為服務的信息進行保護。

這是屬於CAP里面的AP分支。

怎樣禁止自我保護?

在Eureka-server中,修改配置文件,添加

server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com  # eureka服務端實例名稱
  client:
    register-with-eureka: false # 不向注冊中心注冊自己
    fetch-registry: false # 表示自己就是注冊中心,不必檢索其他服務
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/ # 設置與 Eureka Server 交互的地址,可用來查詢注冊的服務
  server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com  # eureka服務端實例名稱
  client:
    register-with-eureka: false # 不向注冊中心注冊自己
    fetch-registry: false # 表示自己就是注冊中心,不必檢索其他服務
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/ # 設置與 Eureka Server 交互的地址,可用來查詢注冊的服務
  server:
    enable-self-preservation: false # 關閉自我檢測
    eviction-interval-timer-in-ms: 2000 # 修改檢查心跳時間 默認是30s,現在改成2s。

enable-self-preservation: false # 關閉自我檢測,一旦關閉自我檢測,其中有任何一台微服務宕機,Eureka就會立刻將他從注冊中心除名。

將其中的一個服務提供者的配置也更改如下。

eureka:
  client:
    register-with-eureka: true # 默認是true表示將自己注冊進服務中心
    fetch-registry: true # 默認是true表示抓取已有的注冊中心,如果是集群必須進行配置
    service-url:
      defaultZone: http://localhost:7001/eureka # 單機版
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

  instance:
    instance-id: payment8001
    prefer-ip-address: true # 代表路徑可以顯示IP地址信息
    lease-expiration-duration-in-seconds: 2 #Eureka在收到最后一次心跳后,等待的時間默認是90s,如果超過等待時間,將會剔除服務
    lease-renewal-interval-in-seconds: 1 # 客戶端默認間隔30s 向服務端發送心跳,現在每間隔1s向服務端發送心跳。

eureka.instance.lease-expiration-duration-in-seconds=2

eureka.instance.lease-renewal-interval-in-seconds=1客戶端默認間隔是30s,向服務端發送心跳,改成每隔1s向服務端發送心跳。

啟動服務后,訪問http://eureka7001.com:7001/

image-20200904111251599

當關閉payment8001服務提供者后,實例立即消失。

使用zookeeper作服務發現與注冊時,服務節點是臨時節點。當服務關閉時,zookeeper會立即去除實例。

導入zookeeper相關的依賴。

<dependencies>
        <!-- SpringBoot整合Web組件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.xzq.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合zookeeper客戶端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--先排除自帶的zookeeper3.5.3-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--添加zookeeper3.4.9版本-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.13</version>
        </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>
server:
  port: 8004

spring:
  application:
    name: cloud-provider-payment #微服務實例名
  cloud:
    zookeeper:
      connect-string: localhost:2181 #zookeeper服務所在的IP地址,默認端口是2181

之后啟動zookeeper服務,並打開zkCli.sh,ls /services,會發現實例名成是cloud-provider-payment。

Consul簡介

官網地址:https://www.consul.io/docs

Consul是一套開源的分布式服務發現和配置管理系統,有HashiCorp公司使用Go語言開發。

提供了微服務系統中的服務治理、配置中心、控制總線等功能。

這些功能中的每一個否可以根據自己的需要單獨使用,也可以一起使用構成全方面的服務網格,總之Consul提供了一種完整的服務網格解決方案。

它具有很多優點。包括:基於raft協議,比較簡潔;支持健康檢查,同時支持HTTP和DNS協議支持擴數據中心的WAN集群,提供圖形界面 擴平台支持,例如Linux,Mac,Windows。

Consul安裝與配置

Consul下載地址: https://www.consul.io/downloads

選擇你所對應的版本,下載壓縮包后,直接解壓。

image-20200905105518316

解壓完成后,只有一個consul.exe文件,通過cmd窗口,輸入consul agent -dev 啟動,然后通過瀏覽器訪問localhost:8500,得到以下界面,算是安裝完成了。

image-20200905105804273

image-20200905110013729

CAP原則

最多只能同時滿足兩個。

CAP理論的核心就是:一個分布式系統不可能同時很好的滿足一致性,可用性和分區容錯性,這三個需求。

因此,根據CAP原理將NoSQL數據庫分成了滿足CA原則,滿足CP原則和滿足AP原則三大類。

CA-單點集群,滿足一致性,可用性的系統,通常在可擴展性上不強大。

CP-滿足一致性,分區容錯性,通常性能上有所損失。(Zookeeper/Consul)

AP-滿足可用性,分區容錯性的系統,通常可能對一致性的要其余不是很嚴格。(Eureka)

組件名 語言 CAP 服務健康檢測 對外暴露接口 SpringCloud集成
Eureka Java AP 可配支持 HTTP 已集成
Consul Go CP 支持 HTTP/DNS 已集成
Zookeeper Java CP 支持 客戶端 已集成

Ribbon簡單概述

SpringCloud Ribbon是基於Netflix Ribbon實現的一套客戶端。(負載均衡工具)

簡單的說,Ribbon是Netflix發布的開源項目,主要功能是提供客戶端的軟件負載均衡算法和服務調用。Ribbon客戶端主鍵提供一系列完善的配置項:如連接超時,重試等。簡單的說,就是在配置文件中列出Load Blance后面的所有機器,Ribbon會自動幫助你基於某種規則去連接這些機器。我們很容易使用Ribbon實現自定義的負載均衡算法。

雖然現在Ribbon已經停止維護,但是還是有不少人使用。

主要的模塊有Ribbon-HTTPClient,Ribbon-eureka,Ribbon-Loadbalance

所謂的負載均衡是什么?

簡單的說就是將用戶的請求分發到多個服務上,從而達到系統的高可用。

常見的負載均衡有Nginx,LVS,硬件F5等。

Ribbon本地負載均衡VS Nginx服務端負載均衡

Nginx是服務器負載均衡,客戶端所有請求都會交給Nginx,然后由Nginx實現轉發請求。即負載均衡是服務端實現的。

Ribbon是本地負載均衡,在調用微服務接口的時候,會在注冊中心上獲取注冊信息,緩存到JVM本地,從而在本地實現RPC遠程調用服務技術。

Ribbon負載均衡是客戶端本地的負載均衡,分為集中式和進程內。

集中式

在服務的消費方和提供方之間使用獨立的負載均衡設施(可以是硬件,如F5,也可以是軟件,如Nginx),由該設施負責訪問請求,通過某種策略轉發到服務的提供方。

進程式

將負載均衡的邏輯集成到消費方,消費方從服務注冊中心獲知有哪些地址可用,然后自己再從這些地址中選擇出一個合適的服務器。Ribbon屬於進程內的負載均衡。他是一個類庫,繼承消費方進程,消費方通過它來獲取到服務提供方的地址。

Ribbon是一個軟負載均衡的客戶端組件,它可以和其他所需請求的客戶端結合使用,例如Eureka,RestTemplate等。

Ribbon的工作原理:第一步先選擇EurekaServer,他會優先選擇在同一個區域內負載均衡較少的Server。

第二步再根據用戶指定的策略,從Server取到的服務注冊列表中選擇一個地址。

其中Ribbon提供了多種策略:比如輪詢,隨機,根據響應時間加權等。

Ribbon依賴如下。

<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
      <version>2.2.1.RELEASE</version>
      <scope>compile</scope>
</dependency>

默認情況下,Eureka-client依賴中包含有ribbon的依賴,不需要再次引入。

RestTemplate中的getForEntity方法返回的是對象,getForObject方法返回的是JSON串。

Ribbon的核心組件IRule

Ribbon默認的負載均衡算法是輪詢,而IRule是根據特定的算法中從服務列表中選取其中一個要訪問的服務。

一共有7個方法。

image-20200905163732232

修改負載均衡算法

將默認的輪詢改為隨機。

首先增加配置類,需要注意的是,自定義的配置類不能被@ComponentScan注解掃描到,所以自定義的IRule不要放在啟動類的子目錄,要與啟動類隔離開。

image-20200905162037590

MySelfRule類

@Configuration
public class MySelfRule {

    @Bean
    public IRule getRule(){
        // 負載均衡算法改為隨機
        return new RandomRule();
    }

}

第二步,需要在主啟動類上添加@RibbonClient注解。然后再啟動。

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args    );
    }
}

啟動Eureka-server,啟動服務提供者payment8001,payment8002,啟動服務消費者consumer-order80.

訪問http://localhost/consumer/payment/getForEntity/1001,會發現被訪問的服務提供者的端口是隨機變化的,因此選取的服務也是隨機的。

Ribbon負載均衡算法原理

輪詢方法:rest接口第幾次請求數對服務集群總數量取余操作,得到結果就是實際調用服務器的下標,每次服務器重啟后rest接口計數從1開始。

例如有兩台服務提供者,instances[0] = 127.0.0.1:8001,instances[1] = 127.0.0.1:8002,兩台實例作為兩台機器,集群總數是2,按照輪詢算法原理。

當第1請求時, 1%2 = 1,所以獲取服務地址是127.0.0.1:8001;

當第2請求時, 2%2 = 0,所以獲取服務地址是127.0.0.1:8002;

當第3請求時, 3%2 = 1,所以獲取服務地址是127.0.0.1:8001;

當第4請求時, 4%2 = 0,所以獲取服務地址是127.0.0.1:8002;

以此類推…

手寫輪詢負載均衡算法

首先創建一個MyLoadBalance接口

public interface MyLoadBalance {
    
     ServiceInstance instances(List<ServiceInstance> serviceInstances);
}

接口的實現。

@Component
@Slf4j
public class MyLoadBalanceImpl implements MyLoadBalance {
	// 原子操作類,底層使用的是CAS
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getAndIncrement(){
        int current = 0;
        int next;
        do {
            current = this.atomicInteger.get();
            next = current > 2147483647 ? 0: current+1;
            //如果CAS自增操作成功,就會退出循環(當期望值是current時才會更改稱為next,否則一直自旋)
        }while (!this.atomicInteger.compareAndSet(current,next));
        log.info("next= "+next);
        return next;
    }


    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        // 服務提供者下標 = 自增的數據 % 服務提供者總數
        int index = getAndIncrement() % serviceInstances.size();
        // 選取成功后返回
        return serviceInstances.get(index);
    }
}

服務消費者使用這種輪詢方法,選取服務提供者。orderController

  @GetMapping("/consumer/payment/lb")
    public String getPaymentUrl(){
        String serviceID = "CLOUD-PAYMENT-SERVICE";
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceID);

        if (instances == null || instances.size() <=0){
            return null;
        }
        ServiceInstance instances1 = loadBalance.instances(instances);
        URI uri = instances1.getUri();
        log.info("url= "+uri);
        return  restTemplate.getForObject(uri+"/payment/lb",String.class);
    }

OpenFeign的基本概念

Feign是一個聲明式WebService客戶端。使用Feign能讓編寫WebService客戶端更加簡單。

他的使用方法是:定義一個服務接口然后在上面添加注解。Feign也能支持可拔插式的編碼器和解碼器。Spring Cloud對Feign進行了封裝,使其能夠支持SpringMVC標准注解和HttpMessageConverters。Feign可以與Eureka和Ribbon組合使用完成負載均衡。

Feign旨在使Java Http客戶端變得更加容易。

前面在使用Ribbon+RestTemplate時,利用RestTemplate對Http請求做封裝處理,形成一套模板話的調用方法。但是在實際開發中,由於對服務依賴的調用可能不止一處,往往一個接口會被多處調用。所以,Feign在此基礎上做了進一步的封裝,由他來幫助我們定義和實現接口。在Feign的實現下,我們只需要使用注解配置接口,即可完成對服務提供方的接口綁定,簡化了使用Spring Cloud Ribbon時,自己封裝服務調用的工作量。

還有一點,默認Feign也已經集成了Ribbon。

OpenFeign的使用

1、新建cloud-consumer-fegin-order80模塊,

2、修改pom.xml

添加依賴

 <dependencies>
        <!--entity-->
        <dependency>
            <groupId>org.xzq.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--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>
        <!--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>

3、創建application.yml配置文件

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

4、寫主啟動類

注意是@Feign注解生效,需要在主啟動類上添加@EnableFeignClients。

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

5、編寫業務類

service

@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
@Component
public interface PaymentFeignService {
    @GetMapping("/payment/get/{id}")
    CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}

controller

@RestController
@Slf4j
public class OrderFeignController {
    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping("/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
           return  paymentFeignService.getPaymentById(id);
    }

}

6、測試feign功能

啟動兩個Eureka-server,啟動payment-8001,payment-8002,然后再啟動feign-order80.

image-20200905204612067

image-20200905204735033

OpenFeign的超時控制

問題描述:在消費者向服務提供者發起請求到最后完成響應的過程中,如果服務提供者在處理過程中消耗的時間大於客戶端消費者等待的時間,客戶端就會java.net.SocketTimeoutException: Read timed out拋出異常。

image-20200905210751668

解決方法:在配置文件中,修改客戶端讀取時間和連接時間盡量讓消費者等待的時間大於提供者處理的時間。這個也就是Feign的超時控制。

server:
  port: 80
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
    register-with-eureka: false
# s設置feign的超時時間,OpenFeign默認只此Ribbon
ribbon:
  # 在兩端正常情況下,網絡連接所用的時間
  ReadTimeout: 5000
 # 建立連接后從服務器讀取到可用資源所用的時間
  ConnectTimeout: 5000

OpenFeign的日志增強

支持的日志級別

  • NONE:默認的,不顯示任何日志
  • BASIC:僅僅記錄請求方法、URL、響應狀態碼以及執行時間
  • HEADERS:除了BASIC中定義的信息之外,還有請求和響應的頭信息
  • FULL:除了HEADERS中定義的信息之外,還有請求和響應的正文以及元數據。

要想在控制台中查看詳細日志,需要設置配置類。

@Configuration
public class FeginLogConfig {

    @Bean
    Logger.Level feignLogger(){
        return feign.Logger.Level.FULL;
    }
}

配置文件中添加需要打印日志的請求方法路徑。

logging:
  level:
   com.guigu.service.PaymentFeignService: debug

啟動服務后,向服務提供方發起請求,在控制台上可以看到以下日志。

image-20200905212806192

image-20200905212845747

未完待續…
下一篇:Hystrix

參考:https://www.bilibili.com/video/BV18E411x7eT


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM