Spring Cloud_22_网关Zuul/介绍与使用(一)
程序员文章站
2022-03-23 12:30:36
...
网关Zuul/介绍与使用(一)
- 在之前的例子中,都是通过浏览器或者HttpClient模拟浏览器向服务发送请求
- 在实际环境中,一个集群肯定是多个服务提供者的,如何统一起来对外使用呢?
- 外部服务不能知道每一个服务提供者在哪, 只需要记住统一提供的出口遍可以
1、Zuul介绍
- Zuul是Netflix的一个子项目
- Zuul提供代理、过滤、路由等功能
- 如果集群中提供API/Web服务需要与外部进行通信,比较好的方式就是添加网关,将集群的服务均隐藏至网关后面,这样做有如下好处
- 对于外部客户端而言,无需关心集群内部结构,只需关心网关在哪
- 对于SpringCloud集群而言,不会过多暴露服务,间接提升了集群的安全性
2、编写第一个Zuul程序
- 建立服务项目:atm_zuul_server
- 建立网关项目(接收外部请求,然后转发至服务项目中):atm_zuul_router
- 我们先简单地将Zuul整合到web应用中,实现一个简单的转发功能
2.1、atm_zuul_server
2.1.1、引入依赖
<!-- Spring Boot Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
2.1.2、启动类/服务提供
package com.atm.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class ZuulServerApp {
// 默认使用8080端口
public static void main(String[] args) {
SpringApplication.run(ZuulServerApp.class, args);
}
@RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
public String hello(@PathVariable String name) {
return "hello, " + name;
}
}
2.2、atm_zuul_router
2.2.1、引入依赖
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atm.cloud</groupId>
<artifactId>atm_zuul_router</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>atm_zuul_router Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- Spring Cloud -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<!-- HttpClient -->
<!-- 为什么还需要引入HttpClient?因为Zuul底层是使用httpclient来请求发送的 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
</dependencies>
<build>
<finalName>atm_zuul_router</finalName>
</build>
</project>
2.2.2、启动类
package com.atm.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy//打开Zuul客户端功能,开启Zuul代理
public class ZuulRouterApp {
public static void main(String[] args) {
SpringApplication.run(ZuulRouterApp.class, args);
}
}
2.2.3、配置application.yml
server:
port: 8085
##Zuul配置转发规则
zuul:
routes:
##路由名称
myServer:
url: http://localhost:8080
2.2.4、访问测试
3、Zuul过滤器运行机制
- 这是一个Http请求的生命周期
- 用户或外部应用会发送一个请求到Zuul(虚线框内则是Zuul处理的一个过程)
-
Zuul提供了四种过滤器(4个阶段,并不是具体的过滤器,每个阶段都包含若干个过滤器)
- ”pre”阶段过滤器:对请求尽心预处理(如:对参数进行设置),然后由routing过滤器处理
- “routing”阶段过滤器:进行转发和获取响应,调用源服务
- “post”阶段过滤器:最后会通过“post”阶段过滤器进行处理,响应给用户
- “error”阶段过滤器:出现异常,则由该阶段过滤器处理
每一个阶段都内置许多过滤器,当然,还可以添加自定义过滤器
- 看看ZuulServlet的一段源码
@Override
public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
try {
init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
// Marks this request as having passed through the "Zuul engine", as opposed to servlets
// explicitly bound in web.xml, for which requests will not have the same data attached
RequestContext context = RequestContext.getCurrentContext();
context.setZuulEngineRan();
try {
preRoute();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
route();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
postRoute();
} catch (ZuulException e) {
error(e);
return;
}
} catch (Throwable e) {
error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}
}