Spring Cloud使用Zuul構建網關

不使用網關會存在的問題?

  • 客戶端多次請求不同的微服務,增加了客戶端的複雜性。
  • 存在跨域問題。
  • 認證複雜,每個服務都需要獨立認證。
  • 難以重構,隨着項目的迭代,可能需要重寫劃分微服務。
  • 某些微服務可能使用了防火牆/瀏覽器不友好的協議,直接訪問有一定困難。

在這裏插入圖片描述

什麼是微服務網關?

微服務網關介於客戶端與服務器端之間,所有的外部請求都會講過微服務網關。
在這裏插入圖片描述
使用微服務網關的優點:

  • 客戶端只需和網關交互,而無需調用特定的微服務接口。
  • 易於監控
  • 易於認證
  • 減少了客戶端與各個微服務之間的交互次數

什麼是Zuul?

Zuul是Netflix開源的微服務網關,可以和Eureka、Ribbon、Hystrix等組件配合使用。其核心似乎一系列過濾器,可完成如下功能。

  • 身份認證與安全:識別每個資源的驗證要求,拒絕不符合要求的請求。
  • 審查與監控:在邊緣位置追蹤有意義的數據和統計結果,從而帶來精確的生產視圖。
  • 動態路由:動態地將請求路由到不同地後端集羣。
  • 壓力測試:逐漸增加指向集羣的流量,以瞭解性能。
  • 負載分配:爲每一種負載類型分配對應地容量,並啓用超出限定值的請求。
  • 靜態響應處理:在邊緣位置直接建立部分響應,從而避免其轉發到內部集羣。
  • 多區域彈性:跨越AWS Region進行請求路由,旨在實現ELB(Elastic Load Balancing)使用的多樣化,已經讓系統的邊緣更貼近系統的使用者。

上述內容截取自書籍 《Spring Cloud與Docker微服務架構與實戰》

Spring Cloud使用Zuul

(1)Eureka Server

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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.dfyang</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</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>

application.xml

server:
  port: 8761
spring:
  application:
    name: eureka-server
eureka:
  client:
    #是否將自己註冊到Eureka Server,由於當前應用爲Eureka Service,故爲false
    register-with-eureka: false
    #是否從Eureka Server獲取註冊信息,由於是單點,所以爲false
    fetch-registry: false
    #與Eureka Server交互的地址
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

啓動類

package com.dfyang;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

啓動項目,訪問localhost:8761成功跳轉頁面即編寫成功
在這裏插入圖片描述

(2)服務投遞者

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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.dfyang</groupId>
    <artifactId>service-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service-producer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</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>

application.xml

server:
  port: 8080
spring:
  application:
    name: service-producer
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

啓動類

package com.dfyang;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableEurekaClient
public class ServiceProducerApplication {

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

提供的服務

package com.dfyang.serviceProducer.Controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProducerController {
    @RequestMapping("/serviceA")
    public String serviceA() {
        return "服務A";
    }

    @RequestMapping("/serviceB")
    public String serviceB() {
        return "服務B";
    }
}

啓動項目,訪問localhost:8761,出現如下即成功
在這裏插入圖片描述

(3)服務消費者

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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.dfyang</groupId>
    <artifactId>service-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service-consumer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</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>

application.yml

server:
  port: 8082
spring:
  application:
    name: service-consumer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

啓動類

package com.dfyang;

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

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ServiceConsumerApplication {

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

使用Fegin遠程調用服務

package com.dfyang.serviceConsumer.controller;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

@Service
@FeignClient(name = "service-producer")
public interface ProducerService {

    @GetMapping("/serviceA")
    public String serviceA();

    @GetMapping("/serviceB")
    public String serviceB();
}

消費服務

package com.dfyang.serviceConsumer.controller;

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

@RestController
public class ConsumerController {

    @Autowired
    private ProducerService producerService;


    @GetMapping("/consumeA")
    public String consumeA() {
        return producerService.serviceA();
    }

    @GetMapping("/consumeB")
    public String consumeB() {
        return producerService.serviceB();
    }
}

啓動項目,輸入localhost:8761
在這裏插入圖片描述
訪問 localhost:8082/consumeA 和 localhost:8082/consumeB
在這裏插入圖片描述
在這裏插入圖片描述
成功!

(4)Zuul網關

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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.dfyang</groupId>
    <artifactId>eureka-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-zuul</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</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>

application.yml

server:
  port: 8084
spring:
  application:
    name: eureka-zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
#爲應用程序顯示詳細的健康指標,並未actuator開啓所有的endpoint
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always

啓動類

package com.dfyang;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
public class EurekaZuulApplication {

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

啓動項目,訪問localhost:8761
在這裏插入圖片描述
輸入localhost:8084/service-consumer/consumeA 和 localhost:8084/service-consumer/consumeB
將出現與訪問 localhost:8082/consumeA 和 localhost:8082/consumeB相同的結果

也就是我們所有的請求都交給了Zuul,再由Zuul將請求轉發到微服務。
訪問 http://localhost:8084/actuator/routes
在這裏插入圖片描述
從上面可以看出
請求的格式爲: http://zuul_host:zuul_port/微服務在Eureka的serviceId/**
如果我們需要將 [微服務在Eureka的serviceId] 替換爲別的,只需要添加如下

zuul:
  routes:
    service-producer: /producer/**
    service-consumer: /consumer/**

訪問ocalhost:8084/consumer/consumeA 和 localhost:8084/consumer/consumeB(但之前的仍然可以訪問)
在這裏插入圖片描述
可以添加忽略的服務

zuul:
  routes:
    service-producer: /producer/**
    service-consumer: /consumer/**
  ignored-services: service-producer,service-consumer

再次訪問,成功!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章