本章节,我们讲解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. 如何用纯 CSS 创作一副国际象棋

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/WyXrjz 可交互视频 ...

  2. Docker工具

    虚拟化 什么是虚拟化 在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源, 如服务器.网络.内存及存储等,予以抽象.转换后呈现出来, 打破实体结构间的 ...

  3. ESP8266入门学习笔记1:资料获取

    乐鑫官网:https://www.espressif.com/zh-hans/products/hardware/esp8266ex/overview 乐鑫资料:https://www.espress ...

  4. JDK1.8 HashMap$TreeNode.rotateLeft 红黑树左旋

    红黑树介绍 1.节点是红色或黑色. 2.根节点是黑色. 3.每个叶子节点都是黑色的空节点(NIL节点). 4 每个红色节点的两个子节点都是黑色.(从每个叶子到根的所有路径上不能有两个连续的红色节点) ...

  5. HDU:2255-奔小康赚大钱(KM算法模板)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Mem ...

  6. Ubuntu添加环境变量

    在 Ubuntu 系统中有两种设置环境变量 PATH 的方法.第一种适用于为单一用户设置 PATH,第二种是为全局设置 PATH. 第一种方法: 在用户主目录下有一个 .bashrc 文件,可以在此文 ...

  7. 妹子图爬取__RE__BS4

    妹子图爬取 页面链接 感谢崔大佬: 原文链接 正则实现代码: import requests import re import os import random class mzitu(): def ...

  8. JAVA中变量的类型及命名规范

    1. 计算机是一种极度精确的机器;2. 要将信息存储在计算机当中,就必须指明信息存储的位置和所需的内存空间;3. 在JAVA编程语言当中,使用声明语句来完成上述的任务; 4. 变量的类型: 5. 变量 ...

  9. poj2449 Remmarguts' Date K短路 A*

    K短路裸题. #include <algorithm> #include <iostream> #include <cstring> #include <cs ...

  10. 移动端click时间、touch事件、tap事件详解

    一.click 和 tap 比较 两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件. singleTap和doubleTap 分 ...