源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all

一、zuul简介

1.1 API 网关

api 网关是整个微服务系统的门面,所有的外部访问需要通过网关进行调度和过滤。它实现了请求转发、负载均衡、校验过滤、错误熔断、服务聚合等功能。

下图是直观的显示api Gateway 在微服务网关中的作用(图片引用自spring boot 官网)。

1.2 zuul

spring cloud 中提供了基础Net flix Zuul 实现的网关组件,这就是Zuul,它除了实现负载均衡、错误熔断、路由转发等功能,还能与spring 其他组件无缝配合使用。

二、项目结构

spring-cloud-feign用例已经实现通过feign实现服务间的调用,且提供了两个业务服务单元(consumer、producer),可以方便直观的测试zuul的路由、负载均衡、和错误熔断等功能,所以本用例在其基础上进行zuul的整合。

  • common: 公共的接口和实体类;
  • consumer: 服务的消费者,采用feign调用产品服务;
  • producer:服务的提供者;
  • eureka: 注册中心;
  • zuul: api网关。

聚合项目目录如下:

zuul 项目目录如下:

三、构建api 网关 zuul

3.1 引入依赖

主要的依赖是 spring-cloud-starter-netflix-zuul

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.0.8.RELEASE</version>
  9. <relativePath/>
  10. </parent>
  11. <artifactId>zuul</artifactId>
  12. <properties>
  13. <java.version>1.8</java.version>
  14. <spring-cloud.version>Finchley.SR2</spring-cloud.version>
  15. </properties>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-web</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-freemarker</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.boot</groupId>
  27. <artifactId>spring-boot-starter-test</artifactId>
  28. <scope>test</scope>
  29. </dependency>
  30. <!--eureka-client-->
  31. <dependency>
  32. <groupId>org.springframework.cloud</groupId>
  33. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  34. </dependency>
  35. <!--zuul-->
  36. <dependency>
  37. <groupId>org.springframework.cloud</groupId>
  38. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  39. </dependency>
  40. </dependencies>
  41. <build>
  42. <plugins>
  43. <plugin>
  44. <groupId>org.springframework.boot</groupId>
  45. <artifactId>spring-boot-maven-plugin</artifactId>
  46. </plugin>
  47. </plugins>
  48. </build>
  49. <dependencyManagement>
  50. <dependencies>
  51. <dependency>
  52. <groupId>org.springframework.cloud</groupId>
  53. <artifactId>spring-cloud-dependencies</artifactId>
  54. <version>${spring-cloud.version}</version>
  55. <type>pom</type>
  56. <scope>import</scope>
  57. </dependency>
  58. </dependencies>
  59. </dependencyManagement>
  60. </project>

3.2 在启动类上添加注解@EnableZuulProxy和@EnableDiscoveryClient

@EnableZuulProxy会自动设置Zuul服务器端点并在其中开启一些反向代理过滤器,以便将请求转发到后端服务器。

  1. @SpringBootApplication
  2. @EnableZuulProxy
  3. @EnableDiscoveryClient
  4. public class ZuulApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(ZuulApplication.class, args);
  7. }
  8. }

3.3 指定注册中心、配置网关的路由规则

zuul 需要指定注册中心的地址,zuul 会从eureka获取其他微服务的实例信息,然后按照指定的路由规则进行请求转发。

  1. server:
  2. port: 8090
  3. # 指定服务命名
  4. spring:
  5. application:
  6. name: zuul
  7. # 指定注册中心地址
  8. eureka:
  9. client:
  10. serviceUrl:
  11. defaultZone: http://localhost:8010/eureka/
  12. # 网关的路由
  13. zuul:
  14. routes:
  15. xxxx: #这个地方的值是可以任意的字符串
  16. path: /producer/**
  17. serviceId: producer
  18. consumer:
  19. path: /consumer/**
  20. serviceId: consumer

3.4 启动eureka、producer、consumer、zuul服务,访问 localhost:8090/consumer/sell/product

四、错误熔断

4.1 zuul 默认整合了 hystrix ,不用导入其他额外依赖

4.2 创建 CustomZuulFallbackProvider并实现FallbackProvider 接口,同时用@Component声明为spring 组件,即可实现熔断时候的回退服务

  1. /**
  2. * @author : heibaiying
  3. * @description : zuul 的熔断器
  4. */
  5. @Component
  6. public class CustomZuulFallbackProvider implements FallbackProvider {
  7. /*
  8. * 定义熔断将用于哪些路由的服务
  9. */
  10. @Override
  11. public String getRoute() {
  12. return "consumer";
  13. }
  14. @Override
  15. public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
  16. return new ClientHttpResponse() {
  17. /**
  18. * 返回响应的HTTP状态代码
  19. */
  20. @Override
  21. public HttpStatus getStatusCode() throws IOException {
  22. return HttpStatus.SERVICE_UNAVAILABLE;
  23. }
  24. /**
  25. * 返回HTTP状态代码
  26. */
  27. @Override
  28. public int getRawStatusCode() throws IOException {
  29. return HttpStatus.SERVICE_UNAVAILABLE.value();
  30. }
  31. /**
  32. * 返回响应的HTTP状态文本
  33. */
  34. @Override
  35. public String getStatusText() throws IOException {
  36. return HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase();
  37. }
  38. @Override
  39. public void close() {
  40. }
  41. /**
  42. * 将消息正文作为输入流返回
  43. */
  44. @Override
  45. public InputStream getBody() throws IOException {
  46. return new ByteArrayInputStream("商城崩溃了,请稍后重试!".getBytes());
  47. }
  48. /**
  49. * 将消息正文作为输入流返回
  50. */
  51. @Override
  52. public HttpHeaders getHeaders() {
  53. HttpHeaders httpHeaders = new HttpHeaders();
  54. httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
  55. return httpHeaders;
  56. }
  57. };
  58. }
  59. }

正确返回了内容、同时返回的http状态码也和我们设置的一样。

五、zuul 过滤器

创建自定义过滤器继承自CustomZuulFilter,当我们访问网关的时候,如果判断session 中没有对应的 code,则跳转到我们自定义的登录页面。

  1. /**
  2. * @author : heibaiying
  3. * @description : 自定义filter过滤器
  4. */
  5. @Component
  6. public class CustomZuulFilter extends ZuulFilter {
  7. /**
  8. * 返回过滤器的类型
  9. */
  10. @Override
  11. public String filterType() {
  12. return FilterConstants.PRE_TYPE;
  13. }
  14. /**
  15. * 返回过滤器的优先级顺序
  16. */
  17. @Override
  18. public int filterOrder() {
  19. return 0;
  20. }
  21. /**
  22. * 从此方法返回“true”意味着应该调用下面的 run()方法
  23. */
  24. @Override
  25. public boolean shouldFilter() {
  26. return true;
  27. }
  28. /**
  29. * ZuulFilter的核心校验方法
  30. */
  31. @Override
  32. public Object run() throws ZuulException {
  33. RequestContext currentContext = RequestContext.getCurrentContext();
  34. HttpServletRequest request = currentContext.getRequest();
  35. String code = (String)request.getSession().getAttribute("code");
  36. if (StringUtils.isEmpty(code)){
  37. // 设置值为false 不将请求转发到对应的服务上
  38. currentContext.setSendZuulResponse(false);
  39. // 设置返回的状态码
  40. currentContext.setResponseStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION.value());
  41. HttpServletResponse response = currentContext.getResponse();
  42. try {
  43. // 跳转到登录页面
  44. response.sendRedirect("/index");
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. return null;
  50. }
  51. }

index.ftl:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <form action="/login" method="post">
  8. <input name="username" type="text">
  9. <button id="btn">输入临时用户名后登录!</button>
  10. </form>
  11. </body>
  12. </html>

六、负载均衡

zuul 默认集成了ribbon 实现了负载均衡。只要启动多个实例即可查看到负载均衡的效果。

这里我们直接在idea 中启动多个实例来测试:

负载均衡测试结果:

七、附:关于版本问题可能导致的 zuul 启动失败

如果出现以下错误导致启动失败,是 spring boot 版本不兼容导致的错误,Finchley SR2版本 spring cloud 中的 zuul 和 spring boot 2.1.x 版本存在不兼容。如果出现这个问题,则将 spring boot 将至 2.0.x 的版本即可,用例中采用的是 2.0.8 版本。在实际的开发中应该严格遵循spring 官方的版本依赖说明。

  1. APPLICATION FAILED TO START
  2. ---
  3. Description:
  4. The bean 'counterFactory', defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration$ZuulCounterFactoryConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulServerAutoConfiguration$ZuulMetricsConfiguration.class] and overriding is disabled.
  5. Action:
  6. Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

spring cloud 版本说明

Release Train Boot Version
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

更多组件的版本说明可以在spring cloud overview 页面查看。

源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all

spring cloud 系列第6篇 —— zuul 服务网关 (F版本)的更多相关文章

  1. Spring Cloud系列(五):服务网关Zuul

    在前面的篇章都是一个服务消费者去调用一个服务提供者,但事实上我们的系统基本不会那么简单,如果真的是那么简单的业务架构我们也没必要用Spring Cloud,直接部署一个Spring Boot应用就够了 ...

  2. spring cloud 系列第1篇 —— eureka 服务的注册与发现 (F版本)

    源码仓库地址:https://github.com/heibaiying/spring-samples-for-all 一.eureka 简介 Spring Cloud Eureka使用Netflix ...

  3. spring cloud系列教程第一篇-介绍

    spring cloud系列教程第一篇-介绍 前言: 现在Java招聘中最常见的是会微服务开发,微服务已经在国内火了几年了,而且也成了趋势了.那么,微服务只是指spring boot吗?当然不是了,微 ...

  4. Spring cloud系列教程第二篇:支付项目父工程图文搭建

    Spring cloud系列教程第二篇:支付项目父工程图文搭建 在讲解spring cloud相关的技术的时候,咱们就模拟订单支付这个流程来讲讲 在这个支付模块微服务搭建过程中,上面的这些技术,都会融 ...

  5. Spring Cloud系列教程第九篇-Eureka自我保护机制

    Spring Cloud系列教程第九篇-Eureka自我保护机制 本文主要内容: 1:自我保护介绍 2:导致原因分析 3:怎么禁止自我保护 本文是由凯哥(凯哥Java:kagejava)发布的< ...

  6. Spring Cloud系列(一):服务注册中心

    一.Spring Cloud简介 Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线).分布式系统的协调导致了样 ...

  7. Spring Cloud架构教程 (三)服务网关(基础)

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: alt 我们使用Spring Cloud Netflix中的Eureka实 ...

  8. spring cloud 系列第7篇 —— sleuth+zipkin 服务链路追踪 (F版本)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.简介 在微服务架构中,几乎每一个前端的请求都会经过多个服务单元协调来提 ...

  9. spring cloud 系列第5篇 —— hystrix+turbine 服务的熔断与监控 (F版本)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.hystrix 简介 1.1 熔断器 在分布式系统中,由于服务之间相互 ...

随机推荐

  1. Delphi png、bmp、gif等图片格式转换成jpg

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  2. 机器学习: Viola-Jones 人脸检测算法解析(二)

    上一篇博客里,我们介绍了VJ人脸检测算法的特征,就是基于积分图像的矩形特征,这些矩形特征也被称为Haar like features, 通常来说,一张图像会生成一个远远高于图像维度的特征集,比如一个 ...

  3. framework7使用问题汇总

    framework7 是个非常漂亮的Html框架,最近有个微信公众号的项目使用到了这个,后期还可以封装成APP. 淘宝版和中文官网都是V1,V2只能看英文版的http://framework7.io/ ...

  4. 深入WPF中的图像画刷(ImageBrush)之1——ImageBrush使用举例

    原文:深入WPF中的图像画刷(ImageBrush)之1--ImageBrush使用举例 昨天我在<简述WPF中的画刷(Brush)  >中简要介绍了WPF中的画刷的使用.现在接着深入研究 ...

  5. 对scrollTop的研究

    本文主要从原生 JS以及jquery来说明scrollTop是如何实现的,以及一些技巧,以及在PC端和移动端使用的差异. 首先用代码表示下如何回到顶部的简单原理 <!doctype html&g ...

  6. OpenGL(二十四) VAO、VBO和着色器使用示例

    1. 新建一个工程,新建一个头文件Shader.h,内容如下: #ifndef _SHADER_H_ #define _SHADER_H_ #include <vector> #inclu ...

  7. AutoEncoder一些实验结果,并考虑

    看之前Autoencoder什么时候,我做了一些练习这里:http://ufldl.stanford.edu/wiki/index.php/Exercise:Sparse_Autoencoder .其 ...

  8. 在Eclipse安装ADT

    Eclipse 3.4 (Ganymede) 启动 Eclipse,然后选择 Help > Software Updates….在出现的对话框中.单击 Available Software 选项 ...

  9. VS2015静态编译libcurl(C++ curl封装类)

    一.最新libcurl静态编译教程(curl-7.51版/curl-7.52版) 1.安装perl,在官网下载,安装好以后,测试perl -v是否成功 2.编译openssl(已编译好的下载地址) p ...

  10. Android指纹识别

    原文:Android指纹识别 上一篇讲了通过FingerprintManager验证手机是否支持指纹识别,以及是否录入了指纹,这里进行指纹的验证. //获取FingerprintManager实例 F ...