0
点赞
收藏
分享

微信扫一扫

十二、Spring cloud服务网关(Zuul)

舍予兄 2022-06-21 阅读 58

一、核心概念

1、网关
  网关是程序或者系统之间的连接节点,扮演者程序或系统之间的门户,允许他们之间通过通讯协议交换信息,他们可能是同构和异构的系统。

  例如:

  • REST API 网关
  • WebServices 网关

2、我对网关的理解
  因为微服务架构会将一个大系统分成一个个独立的子系统,每个子系统都会有独立的 域名 或者 IP,若子系统非常多的话,就会导致使用者需要记住很多 URL,这样显然不是用户友好的。

  而在引入了 Zuul(网关)之后,我们只要记住网关的 IP,然后将各个子系统映射的路径加上即可。比如:

zuul.routes.user-service-provider=/user-service/**

就是将 ​​user-service-provider​​​ 子系统映射为 ​​/user-service/**​​​ 路径。原来我们访问 ​​user-service-provider​​​ 的某个接口,比如:​​http;//localhost:9090/user/find/all​​​,现在通过网关,我们只需要通过:​​http;//localhost:5050/user-service/user/find/all​​​ (5050是网关的端口),就可达到同样的效果。网关的作用就是在访问 ​​http;//localhost:5050/user-service/user/find/all​​​ 时,将请求转换成 ​​http;//localhost:9090/user/find/all​​。

二、整合 Zuul

十二、Spring cloud服务网关(Zuul)_客户端

  创建 Zuul 代理应用:zuul-proxy

(一)添加 Zuul 依赖

<!-- 依赖 Spring Cloud Netflix Zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

(二)激活 Zuul

/**
* 注解 @EnableZuulProxy:激活 Zuul
* 注解 @SpringCloudApplication:激活 @SpringBootApplication、@EnableDiscoveryClient和EnableCircuitBreaker
*/
@EnableZuulProxy
@SpringCloudApplication
public class ZuulProxyApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulProxyApplication.class, args);
}
}

(三)配置 Zuul

# Zuul 代理应用
spring.application.name=zuul-proxy

#服务端口
server.port=5050

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

1、配置 Zuul 路由规则

# /* 当前层级匹配  /** 递归层级匹配
url.pattern=/user-service/**

#指定 user-service-provider(服务映射:zuul.routes.${serviceId}=${url.pattern})
zuul.routes.user-service-provider=${url.pattern}

#配置 Ribbon(这样是白名单方式,一旦引入 Eureka,这项配置需要删除)
user-service-provider.ribbon.listOfServers=http://localhost:9090/

  在如此配置之后,访问 ​​http://localhost:5050/user-service/user/find/all​​​ ,会被 Zuul 转发至 ​​http://localhost:9090/user/find/all​​。

2、配置 HTTP 客户端

注意:实际配置 Ribbon 底层 HTTP 调用客户端,并非 Zuul 独享此功能。

(1)默认客户端:​​HttpClient​​​ 装配类:​​HttpClientRibbonConfiguration​

(2)可配置客户端:​​OkHttpClient​​​ 装配类:​​OkHttpRibbonConfiguration​​ 激活配置:​​ribbon.okhttp.enabled=true​

(三)Zuul 端点
实现:​​​RoutesEndpoint​​​ 路径:​​/actuator/routes​​(即可发现所有的网关中的映射)
过滤器:

三、Spring Cloud 再整合

(一)服务依赖关系

  • eureka-server
  • user-service-provider
  • config-server
  • user-service-client
  • zuul-proxy

(二)将 zuul-proxy 配置为 config-client

在 config-server 中新建 ​​configs/zuul-config.properties​​:

#zuul proxy 配置内容

# /* 当前层级匹配 /** 递归层级匹配
url.pattern.provider=/user-service/**
url.pattern.client=/user-client/**

#指定 user-service-provider(服务映射:zuul.routes.${serviceId}=${url.pattern})
zuul.routes.user-service-provider=${url.pattern.provider}

#指定 user-service-client
zuul.routes.user-service-client=${url.pattern.client}

(三)zuul-proxy 整合作为 配置客户端 和 服务发现客户端

1、增加依赖

<!-- 依赖 Config Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- 增加 Eureka Client 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2、配置 config-client 和 eureka-client

(1)bootstrap.properties(新建)

# Zuul 代理应用
spring.application.name=zuul-proxy

#配置客户端应用关联的应用(这里用配置文件 zuul-config.properties 文件名)
spring.cloud.config.name=zuul-config

#关联 profile
spring.cloud.config.profile=default

#关联 label
spring.cloud.config.label=master

#激活 config server 服务发现
spring.cloud.config.discovery.enabled=true

#config server 应用服务器的名称
spring.cloud.config.discovery.service-id=config-server

#eureka 客户端注册到 eureka 服务器
eureka.client.service-url.defaultZone=http://localhost:7070/eureka

(2)application.properties(改造)

#服务端口
server.port=5050

#配置 Ribbon(这样是白名单方式,一旦引入 Eureka,这项配置需要删除)
#user-service-provider.ribbon.listOfServers=http://localhost:9090/

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

3、激活服务发现
  因为我们在 ​​​ZuulProxyApplication​​​ 引导类上加了 ​​@SpringCloudApplication​​​ 注解,该注解继承了 ​​@EnableDiscoveryClient​​,所以无需在单独加注解激活。

三、过滤器 ZuulFilter

  ​​ZuulFilter​​ 调用链:

  • ​ZuulServlet​​​ /​​ZuulServletFilter​
  • ​ZuulRunner#preRoute()​
  • ​ZuulRunner#route()​
  • ​ZuulRunner#postRoute()​
  • ​FilterProcessor#preRoute()​
  • ​FilterProcessor#route()​
  • ​FilterProcessor#postRoute()​
  • ​FilterProcessor#runFilters()​
  • ​ZuulFilter#runFilter()​
  • ​ZuulFilter#run()​


   ​​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();
}
}

四、Zuul 自动装配

  ​​ZuulServletFilter​​​ 使用范围更大,可以拦截所有 ​​Servlet​​​ ,包括 ​​ZuulServlet​​​ 。
  ​​​ZuulServlet​​ 会有URL匹配模式,url-pattern。

  ​​Zuul​​ 两种激活模式:

1、​​@EnableZuulProxy​

  导入 ​​ZuulProxyMarkerConfiguration​​​,随后生成一个 ​​ZuulProxyMarkerConfiguration.Marker()​​​ Bean,这个 Bean 作为 ​​ZuulProxyAutoConfiguration​​ 装配的前置条件。

注意:​​ZuulProxyAutoConfiguration​​​ 扩展了 ​​ZuulServerAutoConfiguration​​​,所以 ​​ZuulController​​​ 和 ​​ZuulServlet​​ 会被自动装配。

  ​​ZuulController​​​ 由 ​​DispatcherServlet​​​ 来控制,它的映射地址是:​​/*​​​。​​DispatcherServlet​​​ 中注册了一个 ​​ZuulHandlerMapping​​​ ,它控制映射到 ​​ZuulController​​​,具体实现可以参考 ​​ZuulServerAutoConfiguration​​ 中的实现:

@Bean
public ZuulController zuulController() {
return new ZuulController();
}

@Bean
public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController());
mapping.setErrorController(this.errorController);
return mapping;
}

  通过源码分析,​​ZuulController​​​ 将请求委派给 ​​ZuulServlet​​​ ,所以所有的 ​​ZuulFilter​​ 实例都会被执行。

因此,访问 ​​http://localhost:5050/user-service-client/user/find/all​​ ,实际上是将请求递交给 DispatcherServlet 发送请求"/user-service-client/user/find/all"

  调用链:

  • ​DispatcherServlet​
  • ​ZuulHandlerMapping​
  • ​ZuulController​
  • ​ZuulServlet​
  • ​RibbonRoutingFilter​

2、@EnableZuulServer

  导入 ​​ZuulServerMarkerConfiguration​​​ ,随后生成一个 ​​ZuulServerMarkerConfiguration.Marker()​​​ Bean,主要用作装配 ​​ZuulServerAutoConfiguration​​。

  ​​ZuulProxyAutoConfiguration​​​ 与 父类 ​​ZuulServerAutoConfiguration​​​ 区别:​​ZuulProxyAutoConfiguration​​​ 提供了 ​​RibbonRoutingFilter​​。

  调用链:

  • ​DispatcherServlet​
  • ​ZuulHandlerMapping​
  • ​ZuulController​
  • ​ZuulServlet​
  • ​ZuulFilter​


举报

相关推荐

0 条评论