zuul設置熔斷、斷路器

在前面一篇文章中http://blog.csdn.net/tianyaleixiaowu/article/details/77884778,已經講過了獨立使用zuul進行反向代理了。在那篇文章中,沒有使用eureka進行服務發現,而是使用簡單的url配置,直接將用戶請求發送到指定的url。這種作法適合於兼容一些老系統或者沒法進行eureka服務註冊的項目中,當時有一個東西沒有提到,那就是熔斷器。html

咱們將請求分發到多個微服務上,若是其中一個服務掛掉了,那麼請求就會進行漫長的超時等待,最終會返回失敗,甚至會影響整個服務鏈。咱們須要一個熔斷器來及時地處理掛掉的服務,及時響應給用戶信息。java

學過springcloud的都知道hystrix,能夠在feign或者ribbon中使用它來進行熔斷服務降級。zuul也有這樣的功能ZuulFallbackProvider。spring

ZuulFallbackProvider提供了若是某微服務掛掉後,進入自定義處理邏輯的功能。可是須要注意的是,這個熔斷器不支持以url配置的路由,必需要用serviceId的方式路由的方式才能使用熔斷器。這樣咱們就要引入eureka服務中心了。
apache

直接上代碼。json

建立eureka服務中心

項目eureka,pom.xml以下api

<?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">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.tianyalei</groupId>
    <artifactId>eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>eureka</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR3</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>


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

在啓動類上加上EurekaServer表明這是eureka的server所在。app

yml配置文件裏設置一下端口,設置本身不做爲eureka的client,省得把本身也做爲一個客戶端註冊到eureka中。maven

server:
  port: 20000
spring:
  application:
    name: eureka
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false

而後就啓動項目就OK了
訪問localhost:20000,看到界面ide

圖片.png

配置zuul

能夠參考文章開頭提到的那篇zuul的文章,搭建基本骨架。在pom.xml添加eureka的依賴spring-boot

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

啓動類也修改一下註解

@EnableZuulProxy
@SpringCloudApplication
public class TestzuulApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(TestzuulApplication.class, args);
    }
}

yml配置文件裏配置一下Application.name,routes,和eureka的註冊地址。

spring:
  application:
    name: zuul
server:
  port: 9000
zuul:
  routes:
    api-2:
      path: /user/**
      #url: http://localhost:9001/
      serviceId: user
eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka/

注意routes裏原來是用url指定的,這裏用serviceId,serviceId就是微服務在eureka上註冊的名字,對應spring.application.name。

我這裏添加映射/user/**的請求會被分發到user服務中,等會建立個user服務。

下面是關鍵部分,設置熔斷器。

package com.tianyalei.testzuul.fallback;
 
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
 
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
 
@Component
public class UserServiceFallbackProvider implements ZuulFallbackProvider {
 
    @Override
    public String getRoute() {
        return "user";
    }
 
    @Override
    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }
 
            @Override
            public int getRawStatusCode() throws IOException {
                return this.getStatusCode().value();
            }
 
            @Override
            public String getStatusText() throws IOException {
                return this.getStatusCode().getReasonPhrase();
            }
 
            @Override
            public void close() {
 
            }
 
            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("Service-user不可用".getBytes());
            }
 
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
                headers.setContentType(mt);
                return headers;
            }
        };
    }
}

getRoute方法的返回值就是要監聽的掛掉的微服務名字,這裏只能是serviceId,不能是url,指定爲「user」,那麼在user服務不存在時,就會去執行後面代碼的邏輯,設置Code,body什麼的自定義內容返回給調用者。

其實到這裏就能夠測試熔斷效果了,由於咱們並無serviceId爲「user」的服務。因此就會進入到熔斷邏輯裏了。

啓動zuul項目。

圖片.png

能夠看到zuul已經註冊到eureka上了,而後咱們訪問zuul/user,讓它轉發到user服務試試。

圖片.png

能夠看到已經進入到熔斷後的自定義處理了,目的已經達成。

下面咱們試試user服務正常時的狀況。

一樣是建立一個Springboot項目,加入eureka依賴,配置yml

spring:
  application:
    name: user
server:
  port: 9001
eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka/

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

定義個Controller

@RestController
public class UserController {
    @RequestMapping("")
    public Object user() {
        return "from user";
    }
}

啓動user項目,等待eureka發現user服務,有必定的延時才能發現。再次訪問localhost:9000/user。

圖片.png

能夠看到正常進入到user服務了,固然能夠屢次嘗試啓停user服務,看看熔斷器的工做狀況。


總結:

能夠看到zuul的熔斷器主要目的和意義在於針對某個微服務的異常狀態進行控制,並不能具體的針對某個具體的請求方法進行控制,譬如個人請求須要關聯商品、用戶、訂單三個微服務,須要三個服務的返回值組合成一個結果返回給用戶,那麼這個熔斷器就不能作出合適的處理了。固然了,須要關聯多個微服務的請求,咱們是採用feign來完成。feign裏也自帶的有hystrix,能夠更精細地控制某個微服務掛掉後經過熔斷的回調賦予默認值,而後用默認值來組合結果,來保證即使掛掉一個服務,其餘的服務還能正常工做時的用戶請求不會無響應。

參考:https://blog.csdn.net/tianyaleixiaowu/article/details/78064127

相關文章
相關標籤/搜索