SpringCloud | 第六篇: 路由网关(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,页面显示如下:已经能够正确的过滤信息了。



猜你喜欢

转载自blog.csdn.net/qq_38455201/article/details/80784033