1. 程式人生 > >6.閘道器/服務端負載均衡器/服務過濾器(Zuul)

6.閘道器/服務端負載均衡器/服務過濾器(Zuul)

1.Zuul介紹

zuul是一個閘道器和負載均衡器,在通過ribbon或者feign實現了客戶端負載均衡之後,zuul在服務端實現負載均衡。zuul支援用任何JVM語言來編寫規則和過濾條件。zuul充當了一個代理伺服器承擔內部網路的閘道器的角色。如圖:


2.cmd下啟動四個工程(eureka註冊工程/ribbon消費者工程/feign消費者工程/服務提供者工程)



3.建立一個Zuul工程(zuul_test)

(1)pom.xml
<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.tyf</groupId>
  <artifactId>zuul_test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>zuul_test</name>
  <url>http://maven.apache.org</url>

	<!-- 1 -->
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

   <!-- 2 -->
   <dependencies>
	<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</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>
  	</dependencies>
  
  	<!-- 3 -->
  	<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  
 	<!-- 4 -->
  	<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

	<!-- 5 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
  
  
  
</project>
(2)resources/application.yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8770
spring:
  application:
    name: zuul-test

zuul:
  routes:
    api-a:
      path: /test-a/**
      serviceId: feign-consumer-test
      
    api-b:
      path: /test-b/**
      serviceId: ribbon-consumer-test
這裡test-a字首負責將所有的這類請求路由給feign-consumer-test 所以這裡訪問feign-consumer-test的控制器不會直接請求feign-consumer-test的地址,而是通過zuul這個閘道器 不使用zuul訪問feign-consumer-test:http://localhost:8766/feignConsumer/test?name=xxx 使用zuul訪問feign-consumer-test:http://localhost:8770/test-a/test?name=xxx
(3)啟動類
package com.tyf.zuul_test;

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;

/**
 * Hello world!
 *
 */


@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class App 
{
    public static void main( String[] args )
    {
    	SpringApplication.run(App.class, args);
    }
}
(4)啟動zuul工程
通過zuul訪問feign-consumer-test的控制器:http://localhost:8770/test-a/feignConsumer/test?name=xxx 通過zuul訪問ribbon-consumer-test的控制器:http://localhost:8770/test-b/modelController/test

4.zuul做過濾器

直接繼承zuul的過濾器,四個方法說明見註釋(別忘了注入ioc中)

package com.tyf.zuul_test;

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;



/*
 * 
 * 		基礎zuul過濾器:
 * 			1.String filterType():返回一個字串代表這個過濾器在路由的那個階段進行
 * 							pre:路由之前
 * 							routing:路由之時
 * 							post: 路由之後
 * 							error:傳送錯誤呼叫
 * 			2.int filterOrder():返回一個int整數用來排序(從0開始),請求在多個過濾器之間傳遞,傳遞的順序就是這個值
 * 			3.boolean shouldFilter():獲取到請求,如果請求不符合要求可以不讓請求通過,這裡可以實現很多邏輯:
 * 
 * 			4.run():具體的過濾邏輯,這裡檢查請求引數是否有token,這裡訪問url變成如下形式:
 * 					feign-consumer-test的控制器:http://localhost:8770/test-a/feignConsumer/test?name=xxx&token=xxx
 * 					ribbon-consumer-test的控制器:http://localhost:8770/test-b/modelController/test?token=xxx
 * 
 * 
 */

@Component
public class myFiler extends ZuulFilter {

	@Override
	public Object run() {

		RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        Object accessToken = request.getParameter("token");
        System.out.println(accessToken);
        try {
				if(accessToken == null) {
				    	//ctx設定response,直接在這裡進行response
						ctx.setSendZuulResponse(false);
						ctx.setResponseStatusCode(401);
				        ctx.getResponse().getWriter().write("token is empty");				
				        System.out.println("token is null !");
				    return null;
				}
			} catch (Exception e) {e.printStackTrace();}
        
        //如果一切正常,request會被路由到消費者/服務提供者那裡由他們做出response
        return null;
	}

	@Override
	public boolean shouldFilter() {
		return true;
	}

	@Override
	public int filterOrder() {
		//filterOrder:過濾的順序
		return 0;
	}

	@Override
	public String filterType() {
		//過濾器在路由之前起作用
		return "pre";
	}

}

run方法中如果request沒有token引數,則zuul伺服器直接response告訴瀏覽器。如果一切正常則request會通過過濾器再通過路由器傳播

正確的訪問引數:

feign-consumer-test的控制器:http://localhost:8770/test-a/feignConsumer/test?name=xxx&token=xxx
ribbon-consumer-test的控制器:http://localhost:8770/test-b/modelController/test?token=xxx