Spring Cloud | 第六篇: 路由網關(Zuul)

一:Zuul介紹

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

# 身份認證和安全: 識別每一個資源的驗證要求,並拒絕那些不符的請求

# 審查與監控:

# 動態路由:動態將請求路由到不同後端集羣

# 壓力測試:逐漸增加指向集羣的流量,以瞭解性能

# 負載分配:爲每一種負載類型分配對應容量,並棄用超出限定值的請求

# 靜態響應處理:邊緣位置進行響應,避免轉發到內部集羣

# 多區域彈性:跨域AWS Region進行請求路由,旨在實現ELB(ElasticLoad Balancing)使用多樣化

二:創建Zuul模塊

我們基於上一篇的工程,在RediaMallCloud中新增一個模塊Mall_ZuulCenter,新增的步驟請參考《Sping Boot多模塊項目的創建和配置》。其中要注意的是我們在建立新模塊其中一個勾選zuul網關依賴。


新建完成之後,我們得修改父工程的pom和子工程的pom文件

父工程裏面的module變成了四個

<!--在父pom文件當中添加模塊的名稱,子模塊pom中<name>標籤當中的值-->
	<modules>
		<module>Mall_EurekaCenter</module>
		<module>Mall_ManagerService</module>
		<module>Mall_WechatService</module>
		<module>Mall_ZuulCenter</module>
	</modules>

zuul新模塊的pom文件如下:

<?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.smartisan</groupId>
	<artifactId>mallzuulcenter</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>Mall_ZuulCenter</name>
	<description>Demo project for Spring Boot</description>

	<!-- 把原有的parent的信息註釋掉,繼承我們的父工程-->
	<parent>
		<!--<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
		<relativePath/>--> <!-- lookup parent from repository -->
		<groupId>com.smartisan</groupId>
		<artifactId>RediaMallCloud</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</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>
		<!-- JSON Configuration -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.6</version>
		</dependency>
		<!--標籤友好化-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>net.sourceforge.nekohtml</groupId>
			<artifactId>nekohtml</artifactId>
			<version>1.9.22</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>、

配置:application.yml文件

eureka:
  client:
    serviceUrl:
      defaultZone:  http://admin:password@localhost:8761/eureka/
spring:
  application:
    name: zuul_center
  cloud:
    loadbalancer:
        retry:
          enabled: true
  thymeleaf:
    mode: LEGACYHTML5
    cache: false
  http:
    encoding:
      charset: UTF-8
      force: true
      enabled: true

server:
  port: 8050
  tomcat:
      uri-encoding: UTF-8


zuul:
#  max:
#    host:
#      connections: 500
  host:
    socket-timeout-millis: 180000
    connect-timeout-millis: 180000
  routes:
    mall-wechatservice:
      path: /wechat/**
      sensitiveHeaders:
    mall-managerservice:
      path: /manager/**
      sensitiveHeaders:
hystrix:
    command:
        default:
            execution:
                isolation:
                    thread:
                        timeoutInMilliseconds: 180000
ribbon:
    ConnectTimeout: 60000
    ReadTimeout: 60000
    MaxAutoRetriesNextServer: 0
    MaxAutoRetries: 1

在zuul主類上加上註解:@EnableZuulProxy,開啓zuul的功能。@EnableEurekaClient註解向註冊中心註冊。

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

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class MallZuulCenterApplication {

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

我們分別在mall-wechatservice和mall-managerservice編寫兩個接口對外提供服務。

mall-managerservice:

@Controller
public class ManagerController {
    private final Logger logger= LoggerFactory.getLogger(this.getClass());

    @Value("${server.port}")
    String port;
    //get請求
    @ResponseBody
    @RequestMapping("/helloA")
    public String sayHelloA(){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("name","king james");
        map.put("age",33);
        map.put("team","Cleveland Cavaliers");
        map.put("port",port);
        logger.info(JSON.toJSONString(map));
        return JSON.toJSONString(map);
    }

}
@Controller
public class WechatController {
    private final Logger logger= LoggerFactory.getLogger(this.getClass());

    @Value("${server.port}")
    String port;
    //get請求
    @ResponseBody
    @RequestMapping("/helloA")
    public String sayHelloA(){
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("name","kobe");
        map.put("age",36);
        map.put("team","Los Lakers");
        map.put("port",port);
        logger.info(JSON.toJSONString(map));
        return JSON.toJSONString(map);
    }

}

現在整個工程目錄如下:


啓動順序:先啓動Mall_EurekaCenter,再啓動Mall_ZuulCenter,然後再啓動Mall_ManagerService/Mall_WechatService

分別請求http://localhost:8050/manager/helloA和http://localhost:8050/wechat/helloA,頁面顯示如下:



說明Zuul服務網關已經能夠正確的路由到我們的微服務上面去了。

三:zuul服務過濾

編寫服務過濾器

@Component
public class MyZuulFilter extends ZuulFilter {
    private final Logger logger= LoggerFactory.getLogger(this.getClass());
    /**
     * 前置過濾器。
     * 但是在 zuul 中定義了四種不同生命週期的過濾器類型:
     * 1、pre:可以在請求被路由之前調用;
     * 2、route:在路由請求時候被調用;
     * 3、post:在route和error過濾器之後被調用;
     * 4、error:處理請求時發生錯誤時被調用;
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 過濾的優先級,數字越大,優先級越低。
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 是否執行該過濾器。
     * true:說明需要過濾;
     * false:說明不要過濾;
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 過濾器的具體邏輯。
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        logger.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if(accessToken == null) {
            logger.warn("token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}
            return null;
        }
        logger.info("ok");
        return null;
    }
}

再次訪問http://localhost:8050/manager/helloA,頁面顯示如下:已經能夠正確的過濾信息了。



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