大家可以关注一下公众号“Java架构师秘籍

前言

通过前几篇教程的介绍,我们基本上认识了构建一个微服务系统所需要的组件,通过这些组件的结合,我们已经可以搭建一个较为简略的微服务系统了,比如下面的架构图: 

https://img-blog.csdn.net/20180803175652889?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lleWF6aGlzaGFuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

可以看出,该系统架构图包含了服务注册中心eureka-server作为服务注册中心,config-server作为配置中心获取远程Git地址的配置文件信息,在服务的请求处还做了负载均衡,服务之间做了集群分布,实现了高可用,服务之间还可以实现相互调用,由此可见,一个简易的微服务系统就搭建成了。

引出Zuul

上面的架构已经包含了微服务系统的基础功能,但是仍有不足之处:
首先是服务路由的不确定性,在之前的学习中,我们通过restTemplate+ribbon 以及 feign客户端的方式实现了负载均衡,可以实现对高可用服务的消费,但那种直接基于服务名来调用的负载处理并不完全,我们需要有一个更强大的网关控制工具。
其次是缺乏校验功能,当我们需要对一个即有的集群内访问接口,实现外部服务访问时,我们不得不通过在原有接口上增加校验逻辑,这样跟服务之间就存在耦合了,不符合开发的宗旨。
针对上述的不足之处,spring cloud 提供了 Zuul组件来加以完善。
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能,加入了Zuul后的微服务架构将变得更加完善,架构图如下:
https://img-blog.csdn.net/20180803175708387?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lleWF6aGlzaGFuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70
下面用实例带大家领略Zuul的魅力。

创建工程

在创建Zuul工程之前,我们需要先引用之前的工程,读者有疑问可以参考https://blog.csdn.net/yeyazhishang/article/details/81392085

在原有的工程创建新新工程zuul-service,其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.yeya</groupId>
<artifactId>zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

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

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.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>Finchley.SR1</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </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-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>
在程序的启动类上加入注解 @EnableDiscoveryClient 和 @EnableZuulProxy,开启服务注册和服务网关的功能,代码如下:

@SpringBootApplicationbr/>@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulApplication {

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

}

在配置文件application.yml配置如下信息:

eureka:
client:
serviceUrl:
defaultZone:
http://localhost:1111/eureka/
server:
port: 1116
spring:
application:
name: zuul-service
zuul:
routes:
api-a:
path: /clientapi/
serviceId: eureka-client
api-b:
path: /ribbonapi/

serviceId: eureka-ribbon

其中,eureka.client.serviceUrl.defaultZone是服务注册中心的地址,服务的名称为zuul-service,以/clientapi/ 开头的请求都转发给eureka-client服务;以/ribbonapi/开头的请求都转发给eureka-ribbon服务;

配置好信息后,依次启动这几个工程,记得eureka-client要改端口 (1112,1113) 启动两次,然后打开浏览器,多次访问 http://localhost:1116/clientapi/hello,会发现浏览器反复显示

hello : 1112
hello : 1113
同样,多次访问 http://localhost:1116/ribbonapi/consumer ,浏览器会显示相同的结果,说明zuul的确起到了路由转发的作用。

服务过滤

zuul除了能做路由转发之外,还能实现过滤作用,做一些安全的验证功能,下面我们来改造一下zuul-service工程。在工程中创建一个过滤器继承ZuulFilter ,并实现类中的方法,具体实现如下功能;

如果请求地址中有带token,那么过滤器就不做拦截,否则拦截并输出 token is empty,下面是具体代码:

@Component
public class MyFilter extends ZuulFilter {br/>@Override
public String filterType() {
return "pre";
}

@Override
public int filterOrder() {
    return 0;
}

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

@Override
public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    Object accessToken = request.getParameter("token");
    if(accessToken == null) {
        ctx.setSendZuulResponse(false);
        try {
            ctx.getResponse().getWriter().write("token is empty");
        }catch (Exception e){}

        return null;
    }
    return null;
}

}
filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:

pre:路由之前
routing:路由之时
post: 路由之后
error:发送错误调用
filterOrder:过滤的顺序
shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
写好代码后,重启服务,访问
http://localhost:1116/ribbonapi/consumer ,发现浏览器返回

token is empty
加上参数token,重新访问 http://localhost:1116/ribbonapi/consumer?token=11,发现浏览器正常输出

hello : 1112
hello : 1113
至此,zuul的过滤工程成功实现。

总结

zuul作为微服务系统的服务网关,起到了至关重要的作用,所以,一般来说,在生产上的微服务系统中,zuul服务需要做集群分布,避免服务挂了网关失效的情况。
    如果你现在在JAVA这条路上挣扎,也想在IT行业拿高薪,可以参加我们免费的公开课试听学习 干货满满的,选择最适合自己的课程学习,技术大牛亲授,课程内容有:Java工程化、高性能及分布式、高性能、深入浅出。高架构。性能调优、Spring,MyBatis,Netty源码分析和大数据等多个知识点。如果你想拿高薪的,想学习的,想就业前景好的,想跟别人竞争能取得优势的,想进阿里面试但担心面试不过的,你都可以来,q群号为:230419550

先分享几节你们自己看一下 干货满满的 能看懂这些视频再加吧

高可用集群架构技术进阶篇手把手教你玩转Nginx与Docker

链接:https://pan.baidu.com/s/1NL0QKHQMmDkxqF-TzetdaA

密码:w61n

走向架构师,你必须了解的Java虚拟机高级特性

链接:https://pan.baidu.com/s/1hlrZEhVPdWLWb_Wnr9pgtA

密码:rlxn

高并发处理技术老司机带你玩RabbitMq实现性能倍增

链接:https://pan.baidu.com/s/1tdWyeXgXzbWsltY8NlhdaQ

密码:ripd

2018.07.09-T5架构师带你解读Spring源码~手写SpringMVC实战

链接:https://pan.baidu.com/s/1a7HMX5AKCHTAvK3frXSncw 密码:ayru

注:加群要求

1、具有工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加。

2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加。

3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加。

4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加。

5.阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!