微服务:SpringCloud zuul网关
一、存在的问题
在之前的文章中,微服务架构已经初具雏形。但还有一些问题:不同的微服务一般会有不同的网 络地址,客户端在访问这些微服务时必须记住几十甚至几百个地址,这对于客户端方来说太复杂也难以维护。如下图:
前端应用程序调用我们消费者提供的接口会有以下几个问题:
- 客户端会请求多个不同的服务,需要维护不同的请求地址,增加开发难度 (各个消费者ip不同)
- 在某些场景下存在跨域请求的问题
- 加大身份认证的难度,每个微服务需要独立认证(关于微服务认证,可以看我之前的文章,深入的讲解了分布式的授权与认证)
那我们想,能否用同一个ip来解决呢?这样就出现了我们网关的姿势!
通过网关,前端应用程序,只需要调用网关的ip就可以了。在网关就可以找到对应的微服务。
二、网关的概念
什么是微服务网关:
API 网关是一个服务器,是系统对外的唯一入口。 API 网关封装了系统内部架构,为每个客户端提供一个定制的API 。 API 网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP 的访问 API 。服务端通过 API-GW 注册和管理服务。
作用和应用场景:
网关具有的职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。当然,最主
要的职责还是与 “ 外界联系 ” 。
常见的 API 网关实现方式 :
- Kong:基于Nginx+Lua 开发,性能高,稳定,有多个可用的插件 ( 限流、鉴权等等 ) 可以开箱即用。问题:只支持Http 协议;二次开发,自由扩展困难;提供管理 API ,缺乏更易用的管控、配置方式。
Zuul:Netflflix开源,功能丰富,使用 JAVA 开发,易于二次开发;需要运行在 web 容器中,如 Tomcat 。 问题:缺乏管控,无法动态配置;依赖组件较多;处理Http 请求依赖的是 Web 容器,性能不如Nginx;
Traefifik:Go语言开发;轻量易用;提供大多数的功能:服务路由,负载均衡等等;提供WebUI。问题:二进制文件部署,二次开发难度大;UI更多的是监控,缺乏配置、管理能力;
Spring Cloud Gateway:SpringCloud提供的网关服务
Nginx+lua实现:使用Nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用问题:自注册的问题和网关本身的扩展性。
三、zuul实现网关
1、Zuul**简介**
ZUUL 是 Netflflix 开源的微服务网关,它可以和 Eureka 、 Ribbon 、 Hystrix 等组件配合使用, Zuul 组件的核心是一系列的过滤器,这些过滤器可以完成以下功能:
- 动态路由:动态将请求路由到不同后端集群
- 压力测试:逐渐增加指向集群的流量,以了解性能
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
- 静态响应处理:边缘位置进行响应,避免转发到内部集群
- 身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求。Spring Cloud对Zuul进行了整合和增强。
2、搭建一个Zuul网关服务器
(1)一个基础工程
<?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">
<parent>
<artifactId>SpringCloudDemo</artifactId>
<groupId>com.springcloud.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zuul_server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
</project>
server:
port: 8080 #端口
spring:
application:
name: api-zuul-server
package com.springcloud.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class,args);
}
}
其他服务目录:
person-sevice是9002端口,order-service是9001端口,这两个是对外提供的接口。product-service是9010端口,是微服务。
(2)路由配置
# 路由选择配置
zuul:
routes:
service-order:
path: /order-service/**
url: http://127.0.0.1:9001
service-person:
path: /person-service/**
url: http://127.0.0.1:9002
只需要在 application.yml 文件中配置路由规则即可:
- product-service:配置路由id,可以随意取名
- url:映射路径对应的实际url地址
- path:配置映射路径,这里将所有请求前缀为/product-service/的请求,转发到http://127.0.0.1:9002处理
都是可以的,他们都调用了一个微服务。
(3)面向服务的路由配置(从注册中心拿到服务)
添加注册中心依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
添加注册中心配置
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
# 路由选择配置
zuul:
routes:
service-order:
path: /order-service/**
# url: http://127.0.0.1:9001
serviceId: service-order
service-person:
path: /person-service/**
# url: http://127.0.0.1:9002
serviceId: service-person
依然是没有任何问题的!!!
简化配置
zuul:
routes:
service-order: /service-order/**
3、过滤器
zuul有两个核心功能:请求和过滤
ZuulFilter 简介 :
Zuul 中的过滤器跟我们之前使用的 javax.servlet.Filter 不一样, javax.servlet.Filter 只有一种类型,可
以通过配置 urlPatterns 来拦截对应的请求。而 Zuul 中的过滤器总共有 4 种类型,且每种类型都有对
应的使用场景。
PRE :这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请
求的微服务、记录调试信息等。
ROUTING :这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用
Apache HttpClient 或 Netfifilx Ribbon 请求微服务。
POST :这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP
Header 、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器。
Zuul 提供了自定义过滤器的功能实现起来也十分简单,只需要编写一个类去实现 zuul 提供的接口
public abstract ZuulFilter implements IZuulFilter{
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 来自IZuulFilter
Object run() throws ZuulException;// IZuulFilter
}
ZuulFilter 是过滤器的顶级父类。在这里我们看一下其中定义的 4 个最重要的方法。
- shouldFilter :返回一个 Boolean 值,判断该过滤器是否需要执行。返回 true 执行,返回 false不执行。
run :过滤器的具体业务逻辑。
filterType :返回字符串,代表过滤器的类型。包含以下4种:
pre :请求在被路由之前执行
routing :在路由请求时调用
- post :在routing和errror过滤器之后调用
- error :处理请求时发生错误调用
- filterOrder :通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
生命周期:
4、自定义过滤器
package com.springcloud.demo.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @ClassName LoginFilter
* @Description
* @Author 戴书博
* @Date 2020/5/28 16:24
* @Version 1.0
**/
@Component
public class LoginFilter extends ZuulFilter {
/**
* 类型:
* pre
* routing
* post
* 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 {
System.out.println("================进入过滤器=================");
//获取上下文对象
RequestContext ctx = RequestContext.getCurrentContext();
//获取request对象
HttpServletRequest req = ctx.getRequest();
//从请求中获取token
String token = req.getParameter("access-token");
//判断
if(token == null || token.equals("")){
// 没有token,登录校验失败,拦截
ctx.setSendZuulResponse(false);
// 返回401状态码。也可以考虑重定向到登录页。
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
// 校验通过,可以考虑把用户信息放入上下文,继续向后执行
return null;
}
}
在我们之前写的授权与认证中,使用了一个微服务认证。这里简单写一下。
zuul出现的问题:
- 性能问题 :Zuul1x版本本质上就是一个同步Servlet,采用多线程阻塞模型进行请求转发。简单讲,每一个请求,Servlet容器要为该请求分配一个线程专门负责处理这个请求,直到响应返回客户端这个线程才会被释放返回容器线程池。如果后台服务调用比较耗时,那么这个线程就会被阻塞,阻塞期间线程资源被占用,不能干其它事情。我们知道Servlet容器线程池的大小是有限制的,当前端请求量大,而后台慢服务比较多时,很容易耗尽容器线程池内的线程,造成容器无法接受新的请求。
- 不支持任何长连接,如websocket
源码:git@gitee.com:Zesystem/springclouddedemowangguan.git
还没有评论,来说两句吧...