本章节,我们讲解springcloud重要组件:微服务网关Zuul。如果有同学从第一章看到本章的,会发现我们已经讲解了大部分微服务常用的基本组件。

已经讲解过的:

一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目

一起来学Spring Cloud | 第二章:服务注册和发现组件 (Eureka)

一起来学Spring Cloud | 第三章:服务消费者 (负载均衡Ribbon)

一起来学Spring Cloud | 第四章:服务消费者 ( Feign )

一起来学Spring Cloud | 第五章:熔断器 ( Hystrix)

本章正在讲解的:一起来学Spring Cloud | 第六章:服务网关 ( Zuul)

下章即将讲解的: 一起来学Spring Cloud | 第七章:分布式配置中心(Spring Cloud Config)

刚入门的同学,如果把前面这七章都理解清楚,并且自己搭建一遍,在工作中,我们已经可以搭建一个最简单的微服务项目了,我曾经看过一个创业公司,他们使用微服务框架时,就用以上的组件在生产上运行着简单的后台业务系统。

一、Zuul简介:

Zuul是Netflix开源的微服务网关,它可以和Eureka、Feign、hystrix等组件配合使用,Zuul的核心是一系列过滤器,它主要功能是路由转发和过滤器。

在实际项目中,一个复杂的业务系统后台,少则几十个服务模块,多则成百上千,随着业务场景的不断变更,我们的系统也会不断在演变,就会遇到如下的几个问题:

1.  如果存在跨域请求,多个微服务在一定的场景下处理相对复杂。

2.  客户端多次请求不同的微服务,增加了客户端的复杂性。

3.  认证复杂,每个微服务都需要独立认证。

4.  难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个微服务合并成一个或者将一个微服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很能实施。

5.  某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定困难。

Zuul提供的作用:

1. 提供统一服务入口,微服务对前台透明

2. 聚合后台服务,节省流量,提升性能

3. 安全,过滤,流控等API管理功能

4. 提供统一服务出口,解耦

二、Zuul实现路由功能:

1. 在前面2章讲解的两个服务模块上,新增两个方法,模拟前端请求,做为本次zuul的测试接口
springcloud-ribbon-client模块的RibbonController类,增加/testzuul接口,具体模块信息参考:一起来学Spring Cloud | 第三章:服务消费者 (负载均衡Ribbon)

package com.haly.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import com.haly.service.RibbonService; @RestController
public class RibbonController {
@Autowired
RibbonService ribbonService; @GetMapping(value = "/getHello")
public String getHello(@RequestParam String name) {
return ribbonService.getHello(name);
} @GetMapping(value = "/testzuul")
public String testzuul(@RequestParam String name) {
return name +"这是springcloud-ribbon-clientd的服务接口";
} }

springcloud-feign-client模块的FeignController类,增加/testzuul接口,具体模块信息参考:一起来学Spring Cloud | 第四章:服务消费者 ( Feign )

package com.haly.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import com.haly.romote.FeignRemoteService; @RestController
public class FeignController { @Autowired
FeignRemoteService feignRemoteService; @GetMapping(value = "/getHello")
public String getHello(@RequestParam String name) {
return feignRemoteService.hello(name);
} @GetMapping(value = "/testzuul")
public String testzuul(@RequestParam String name) {
return name +",这是springcloud-feign-client的服务接口";
}
}

2. 新建一个新的zuul服务工程,名称为:springcloud-zuul-server

①:修改pom.xml文件,parent标签引用的是父文件,具体父文件配置,参考:一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目

<?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>com.haly</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent> <groupId>com.haly</groupId>
<artifactId>springcloud-zuul-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-zuul-server</name>
<description>新建一个zuuld项目</description> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

②:新增模块启动类SpringcloudZuulServerApplication

注解@EnableZuulProxy,表示开启zuul的功能,它默认也具有@EnableCircuitBreaker和@EnableDiscoveryClient两个注解的功能

package com.haly;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @EnableZuulProxy
@SpringBootApplication
public class SpringcloudZuulServerApplication { public static void main(String[] args) {
SpringApplication.run(SpringcloudZuulServerApplication.class, args);
} }

③:application.properties加上以下的配置代码:

server.port=9700
spring.application.name=springcloud-zuul-server
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/ zuul.ignored-services: "*" zuul.routes.a.path = /api/a/**
zuul.routes.a.serviceId = springcloud-feign-client zuul.routes.b.path = /api/b/**
zuul.routes.b.serviceId = springcloud-feign-client

先解释下配置含义

zuul.ignored-services: "*"  : 之前我们说过可以用服务名直接访问接口,如果我们不想向外界暴露除了application.properties配置映射的服务接口,配置这个属性,只能通过zuul映射的路径访问。

zuul.routes.a.path = /api/a/**
zuul.routes.a.serviceId = springcloud-feign-client

当我们访问zuul服务模块时,只要包含 /api/a/ 路径的服务请求,默认请求到springcloud-ribbon-client模块上的接口

zuul.routes.b.path =  /api/b/**
zuul.routes.b.serviceId = springcloud-feign-client

同理,当我们访问zuul服务模块时,只要包含 /api/b/ 路径的服务请求,默认请求到springcloud-feign-client模块上的接口

3. 运行项目

启动 注册中心 springcloud-eureka-server,启动springcloud-ribbon-client服务模块,启动springcloud-feign-client服务模块,启动springcloud-zuul-server模块

在这里首先我要表达歉意,在第一章搭建多模块的微服务项目时,我使用的springcloud和springboot的版本会有问题,所以本章节启动springcloud-zuul-server模块时报错,具体报错如下:

原因是springboot与springcloud的版本不一致导致的,以后有同学遇到同样问题,记得将对应的版本号改成一致

在实际开发过程中,我们详细的版本对应关系:

现在我们将父pom中springcloud的版本号修改为:Greenwich.SR1 ,再启动springcloud-zuul-server服务模块,可以启动成功了,eureka上服务信息如下:

打开浏览器访问访问zuul服务的端口9700:http://localhost:9700/api/a/testzuul?name=young码农,我们发现/api/b/*的请求路由到 springcloud-ribbon-client模块

打开浏览器访问zuul服务的端口9700:http://localhost:9700/api/b/testzuul?name=young码农,我们发现/api/b/*的请求路由到 springcloud-feign-client模块

三、Zuul实现服务过滤:

zuul不仅只是路由,并且还能过滤,可以用来做一些安全验证和日志记录,我写一个简单的接口执行时间记录的功能

新建一个类:BaseZuulFilter

package com.haly.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; @Component
public class BaseZuulFilter extends ZuulFilter {
protected final Logger logger = LoggerFactory.getLogger(getClass());
// 单例多线程 开始时间绑定在线程上
private ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();

   @Override
public String filterType() {
// 在请求被处理之后,会进入该过滤器
return "post";
}

   @Override
public int filterOrder() {
return 0;
} @Override
public boolean shouldFilter() {
// 请求开始计时
long startTime = System.currentTimeMillis();
startTimeThreadLocal.set(startTime);
return true;
} @Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
String requestURI = String.valueOf(context.get("requestURI")); // 请求结束时间
Long startTime = startTimeThreadLocal.get();
Long endTime = System.currentTimeMillis();
logger.info("[进入zuul日志记录功能] RequestURI:{}, {}:ms", requestURI, endTime - startTime);
return null;
}
}
 filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
 pre:路由之前
 routing:路由之时
 post: 路由之后
 error:发送错误调用
 filterOrder:过滤的顺序
 shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
 run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
 
浏览器分别请求zuul服务模块:http://localhost:9700/api/b/testzuul?name=young码农,http://localhost:9700/api/b/testzuul?name=young码农,会打印如下日志:
2019-05-25 16:41:07.228  INFO 20984 --- [io-9700-exec-10] com.haly.filter.BaseZuulFilter           : [进入zuul日志记录功能]请求地址:/testzuul, 耗时0:ms
有兴趣的可以自己参考上面代码,做一个简单接口权限验证的功能。

四、总结:

当前为止,项目结构:

 

一起来学Spring Cloud | 第六章:服务网关 ( Zuul)的更多相关文章

  1. Spring Cloud(六)服务网关 zuul 快速入门

    服务网关是微服务架构中一个不可或缺的部分.通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由.均衡负载功能之外,它还具备了权限控制等功能.Spring Cloud Netflix中 ...

  2. Spring Cloud(七)服务网关 Zuul Filter 使用

    上一篇文章中,讲了Zuul 转发,动态路由,负载均衡,等等一些Zuul 的特性,这个一篇文章,讲Zuul Filter 使用,关于网关的作用,这里就不再次赘述了,重点是zuul的Filter ,我们可 ...

  3. spring cloud深入学习(十一)-----服务网关zuul

    前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个 ...

  4. 一起来学Spring Cloud | 第五章:熔断器 ( Hystrix)

    在微服务项目中,一个系统可以分割成很多个不同的服务模块,不同模块之间我们通常需要进行相互调用.springcloud中可以使用RestTemplate+Ribbon和Feign来调用(工作中基本都是使 ...

  5. 一起来学Spring Cloud | 第七章:分布式配置中心(Spring Cloud Config)

    上一章节,我们讲解了服务网关zuul,本章节我们从git和本地两种存储配置信息的方式来讲解springcloud的分布式配置中心-Spring Cloud Config. 一.Spring Cloud ...

  6. Spring Cloud实战之初级入门(六)— 服务网关zuul

    目录 1.环境介绍 2.api网关服务 2.1 创建工程 2.3 api网关中使用token机制 2.4 测试 2.5 小结 3.一点点重要的事情 1.环境介绍 好了,不知不觉中我们已经来到了最后一篇 ...

  7. Spring Cloud 系列之 Gateway 服务网关(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Gateway 服务网关(一) 本篇文章讲解 Gateway 网关的多种路由规则.动态路由规则(配合服务发现的路由规则 ...

  8. Spring Cloud 系列之 Gateway 服务网关(三)

    本篇文章为系列文章,未读第一集的同学请猛戳这里: Spring Cloud 系列之 Gateway 服务网关(一) Spring Cloud 系列之 Gateway 服务网关(二) 本篇文章讲解 Ga ...

  9. Spring Cloud 系列之 Gateway 服务网关(四)

    本篇文章为系列文章,未读第一集的同学请猛戳这里: Spring Cloud 系列之 Gateway 服务网关(一) Spring Cloud 系列之 Gateway 服务网关(二) Spring Cl ...

随机推荐

  1. 不使用脚手架的 vue 应用

    工作中的项目不止有页面繁多的模块化项目,还会只有一两个页面的类似于填写信息参与活动的活动页.这个时候,就可以回归以前的三剑客模式,在 index.html 里引用 vue.js 进行开发. 关键点: ...

  2. PHP安装Xcache扩展

    简述 XCache 是一个又快又稳定的 ​PHP opcode 缓存器. 经过良好的测试并在大流量/高负载的生产机器上稳定运行. 经过(在 linux 上)测试并支持所有现行 ​PHP 分支的最新发布 ...

  3. 如何在微信中发送"相册"文件时有选择性地显示视频文件

    相信很多微信用户在使用微信给朋友,同事发送相册中的文件时,微信会显示你手机中的视频文件,这样很不方便. 如果要完全不显示视频文件: 随便在手机中建立一个文件夹,名字叫 ".nomedia&q ...

  4. mysql Plugin ‘InnoDB’ init function returned error

    问题描述: 非正常关闭mysql,同时更改了my.cnf 导致启动时不支持innodb,出现如下错误:   [ERROR] Plugin ‘InnoDB’ init function returned ...

  5. list_for_each_entry()函数分析

    list_for_each原型: #define list_for_each(pos, head) \ for (pos = (head)->next, prefetch(pos->nex ...

  6. PAT Basic 1082

    1082 射击比赛 本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军:谁差得最远,谁就是菜鸟.本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟.我们假设靶心在原 ...

  7. HDU 4812 D Tree 树分治

    题意: 给出一棵树,每个节点上有个权值.要找到一对字典序最小的点对\((u, v)(u < v)\),使得路径\(u \to v\)上所有节点权值的乘积模\(10^6 + 3\)的值为\(k\) ...

  8. 【Netty】Netty入门之WebSocket小例子

    服务端: 引入Netty依赖 <!-- netty --> <dependency> <groupId>io.netty</groupId> <a ...

  9. 细嚼慢咽 Mongoose 5

    此文已由作者黄锴授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 前言 由于Mongoose一直没有中文文档,加上现在市面上充斥着太多"快速上手",很多中文 ...

  10. Cookie和Session的作用和工作原理

    一.Cookie详解 (1)简介 因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现.在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两饮料 ...