搭建Zuul网关

在上一个项目的
configCenter
父项目中新增maven Module
子项目zuul_gateway
;
该服务为网关服务,所有请求先经过该网关后,由网关负责去注册中心获取对应服务真实地址,然后在本地做负载均衡请求真实服务器地址。
本网关服务对外端口:8102
app-member会员服务端口:8101
app-order订单服务端口:8103
该网关服务需要将自己注册到eureka注册中心,所以需要EurekaServer服务。

pom.xml文件内容:
<?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>configCenter</artifactId>
<groupId>configCenter</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zuul_gateway</artifactId>
<dependencies>
<!--spring-cloud2.0比较支持zuul网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
</project>
application.yml 文件内容:
server:
port: 8102
###服务别名--该服务注册到服务中心的名称
spring:
application:
name: service-zuul
zuul:
routes:
### 定义转发规则,这里的api-a是自定义的,也可以修改为api-member
api-a:
### 客户端请求http://127.0.0.1/api-member开头的,都会转发到会员服务
path: /api-member/**
#这里的app-member是会员服务在注册中信中的别名
#zuul网关默认整合ribbon,自动实现负载均衡轮训效果
serviceId: app-member
api-b:
path: /api-order/**
serviceId: app-order
eureka:
client:
serviceUrl:
###当前会员服务注册到eureka服务中心(所有eureka集群地址)
defaultZone: http://eureka-server1:7100/eureka
项目启动 ZuulGatewayApplication.java
package zuul_gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
//@EnableEurekaClient 将当前服务注册到Eureka
@EnableEurekaClient
//开启Zuul网关代理
@EnableZuulProxy
public class ZuulGatewayApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ZuulGatewayApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ZuulGatewayApplication.class);
}
}
启动网关服务并测试

- 启动网关服务之前,需要先启动如下服务:
-
springcloud-eureka-service
注册中心服务。端口:7100
-
api-member-service-impl
会员服务.端口:8101
-
api-order-service-impl
订单服务, 端口:8103
-
- 启动本网关
zuul_gateway
服务,端口:8102
- 访问EurekaServer:http://127.0.0.1:7100,可以看到
会员服务
,订单服务
,网关服务
,三个服务均已经注入到注册中心。
image.png
-
直接访问订单服务(不通过网关):http://127.0.0.1:8103:
image.png
-
直接访问会员服务(不通过网关):http://127.0.0.1:8101:
image.png
- 通过网关访问会员服务:http://127.0.0.1:8102/api-member/
image.png
- 通过网关访问订单服务:http://127.0.0.1:8102/api-order/
image.png
在zuul_gateway网关项目中添加过滤器
- 在网关中添加过滤器,过滤规则: 获取参数
userToken
, 如果该参数为空则直接返回.当然这是是一个演示,也可以过滤一些其他规则. - 在zuul_gateway项目中添加
TokenFilter.java
过滤器.
package zuul_gateway;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 网关token过滤器
* @author liangxifeng
* @date 2020-08-09
*/
@Component
public class TokenFilter extends ZuulFilter {
//过滤器类型pre,表示请求之前执行
@Override
public String filterType() {
return "pre";
}
//过滤器执行顺序,当一个请求在同一阶段存在多个过滤器的时候,多个过滤器执行顺序
@Override
public int filterOrder() {
return 0;
}
//判断过滤器是否生效,这里return true生效
@Override
public boolean shouldFilter() {
return true;
}
/**
* 拦截业务逻辑代码
* 所有通过网关的请求,都必须通过该方法验证,才能继续放行
* 如果验证失败,则返回401
*/
@Override
public Object run() throws ZuulException {
//案例:拦截所有服务接口,判断服务接口上是否有传递userToken参数
//1. 获取上下文
RequestContext currentContext = RequestContext.getCurrentContext();
//2. 获取Request
HttpServletRequest request = currentContext.getRequest();
//3. 获取token
String userToken = request.getParameter("userToken");
if (StringUtils.isEmpty(userToken)) {
//如果token为空,则网关直接返回
currentContext.setSendZuulResponse(false);
currentContext.setResponseBody("userToken is null");
currentContext.setResponseStatusCode(401);
return null;
}
//正常调用其他服务接口
return null;
}
}
- 此时重启zuul_gateway服务, 再次通过网关访问会员服务, http://127.0.0.1:8102/api-member, 如果没有
userToken
参数,回直接返回:
image.png
- 在请求中添加
userToken
参数, 就可以直接访问到 会员服务了. http://127.0.0.1:8102/api-member?userToken=123456
image.png
动态Zuul网关路由转发
-
以上Zuul路由转发规则只配置两两个
api-member
和api-order
, 如果网关项目正在运行,需要新增路由规则,就需要修改配置文件,重启网关服务了. 这里配置一下动态读取配置文件. 不需要重启服务. -
也就是将路由配置信息作为配置文件
service-zuul-dev.yml
放到git版本库中,在git中新增zuul_config
目录作为网关服务配置文件存储目录, 内容如下: git地址: https://github.com/liangxifeng833/gkconfig/blob/master/zuul-config/service-zuul-dev.ymlzuul: routes: ### 定义转发规则,这里的api-a是自定义的,也可以修改为api-member api-a: ### 客户端请求http://127.0.0.1/api-member开头的,都会转发到会员服务 path: /api-member/** #这里的app-member是会员服务在注册中心中的别名 #zuul网关默认整合ribbon,自动实现负载均衡轮训效果 serviceId: app-member api-b: path: /api-order/** serviceId: app-order
-
修改pom.xml文件,新增分布式配置中心相关依赖
<!-- 分布式配置中心相关依赖#################################start --> <!-- springCloud整合config-server分布式配置中心client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency> <!--actuaor监控中心,手动触发刷新本地读取git中配置文件缓存所用--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 分布式配置中心相关依赖#################################end -->
-
然后将
zuul_gateway
网关项目application.yml
修改为bootstrap.yml
, 因为SpringCloud
里面有个“启动上下文”,主要是用于加载远端的配置
,也就是加载ConfigServer
里面的配置,默认加载顺序为:加载bootstrap.里面的配置 --> 连接configserver,加载远程配置 --> 加载application.里面的配置; 总结:这里需要借助于“启动上下文”来处理加载远程配置;bootstrap.yml
内容如下:server: port: 8102 ###服务别名--该服务注册到服务中心的名称 spring: application: #这里的服务别名=要读取git的配置文件的服务名称 #配置文件命名规范:服务名-环境.yml(service-zuul-dev.yml) name: service-zuul cloud: config: #读取配置文件的环境(service-zuul-dev.yml)中的dev profile: dev #读取配置文件服务的config-server环境 #也就是配置中心服务端在eureka注册的服务别名 discovery: service-id: config-server #开启读取权限 enabled: true #actuaor监控中心,开启所有端点,手动触发刷新本地缓存读取最新git配置文件所用 management: endpoints: web: exposure: include: "*" # * 在yaml 文件属于关键字,所以需要加引号 eureka: client: serviceUrl: ###当前会员服务注册到eureka服务中心(所有eureka集群地址) defaultZone: http://eureka-server1:7100/eureka/
-
修改项目入口文件
ZuulGatewayApplication
, 新增方法如下:
作用是修改git中配置文件信息后, 手动调用接口刷新网关读取远程配置文件信息所用.// zuul配置使用git中config实现实时更新 @RefreshScope @ConfigurationProperties("zuul") public ZuulProperties zuulProperties() { return new ZuulProperties(); }
-
重启该项目后, 访问: http://127.0.0.1:8202/api-member?userToken=12, 如果能够正常访问就代表配置成功了.
-
此时我们后端,开启两个member服务, 作为集群.
zuul
可以自动实现ribbon负载均衡. 以下两次请求代表分别请求到了两个会员服务(默认负载均衡为: 轮训算法)
image.png
image.png
我的视频总结地址:https://www.bilibili.com/video/BV1z64y1F727/
我的源代码地址:https://github.com/liangxifeng833/springcloud/tree/master/configCenter/zuul_gateway