热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:springcloud入门系列六:使用Zuul实现API网关服务

篇首语:本文由编程笔记#小编为大家整理,主要介绍了springcloud入门系列六:使用Zuul实现API网关服务相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了spring cloud 入门系列六:使用Zuul 实现API网关服务相关的知识,希望对你有一定的参考价值。



 

通过前面几次的分享,我们了解了微服务架构的几个核心设施,通过这些组件我们可以搭建简单的微服务架构系统。比如通过Spring Cloud Eureka搭建高可用的服务注册中心并实现服务的注册和发现;

通过Spring Cloud Ribbon或Feign进行负载均衡;通过Spring Cloud Hystrix进行服务容错保护以避免故障蔓延。微服务搭建好了之后我们肯定会提供给外部系统一些统一的RESTFul API服务接口进行调用,

但是当外部系统调用我们的RESTful API的时候,怎么确定它需要的功能具体是哪个服务提供的呢?这个就涉及到一个路由规则和服务实例列表的维护问题。

这就引入了我们今天的主角--Spring Cloud Zuul,它是基于Netflix Zuul实现的API网关组件。它可以解决两个大问题:



  1. 就是我们上面提到的路由规则和服务实例的维护问题

  2. 对于一些校验(比如登录校验等)冗余问题。 按照我们的习惯的做法,是在每个服务中都需要加入这些校验,但是这样会导致代码冗余并且维护也比较麻烦,有了Spring Cloud Zuul这个网关服务之后,我们可以将这些共通的校验放到网关里面统一维护。

好,接下来我们就来看下怎么实现这个网关服务。

一、构建网关,配置路由

 这里我们还是需要使用到前面的hello-service和feign-consumer服务。我们之前把feign-consumer作为服务消费者,但是别忘了在eureka体系里面,每个服务既是服务提供者又是服务消费者,所以feign-consumer也是一个服务提供者,并且http://localhost:9001/feign-consumer等接口就是它提供的服务。

接下来我们构建一个网关服务,代码结构如下:

  

代码实现步骤:



  1. 新建maven工程api-gateway

  2. 修改POM文件

    <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">
    <modelVersion>4.0.0modelVersion>
    <groupId>com.samgroupId>
    <artifactId>api-gatewayartifactId>
    <version>0.0.1-SNAPSHOTversion>

    <parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>1.5.1.RELEASEversion>
    parent>
    <properties>
    <javaVersion>1.8javaVersion>
    properties>

    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-dependenciesartifactId>
    <version>Camden.SR6version>
    <type>pomtype>
    <scope>importscope>
    dependency>
    dependencies>
    dependencyManagement>
    <dependencies>

    <dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-zuulartifactId>
    dependency>
    dependencies>

    project>



  3. 新建启动类

    /**
    * @EnableZuulProxy 开启Zuul 的API网关服务功能
    *
    */
    @EnableZuulProxy
    @SpringCloudApplication
    public class GateWayApp {
    public static void main(String[] args) {
    SpringApplication.run(GateWayApp.
    class, args);
    }
    }



  4. 新建application.properties

    server.port=5555
    spring.application.name
    =api-gateway
    #增加路由规则的配置
    #通过zuul.routes.
    .path和zuul.routes..url进行配置,为路由的名字,可以任意指定,但是一组path和url的路由名要相同
    #如下面的例子:所有满足/api-a/** 规则的访问都会被路由转发到//localhost:9001的地址
    #也就是说,我们访问http://localhost:5555/api-a/hello的时候,API网关服务就会将该请#求路由到 http://localhost
    :9001/hello提供的微服务接口上
    zuul.routes.api-a.path=/api-a/**
    zuul.routes.api-a.url=
    http://localhost:9001
    zuul.routes.api-b.path=/api-b/**
    zuul.routes.api-b.url=http://localhost:9090

     



  5. 测试,启动eureka、hello-service、feign-consumer以及本次新加的api-gateway服务,然后访问http://localhost:5555/api-a/feign-consumer

    成功访问到了feign-consumer的服务接口--feign-consonsumer。



以上步骤实现了传统路由的配置,这种配置有个大的缺点,就是需要手工在application.properties文件中进行路由规则的配置,当服务很多的时候,维护工作量就会很大。为了减小维护成本,还有另外一种路由--面向服务的路由。

二、面向服务的路由

Spring Cloud Zuul和Eureka进行整合,我们可以让路由的path不是映射具体的url,而是具体的某个服务,而服务的url则交给Eureka服务发现机制自动维护,这类路由就是面向服务的路由。具体代码配置如下:



  1. 修改POM文件,引入Eureka依赖


    <dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-eurekaartifactId>
    dependency>



  2. 修改application.properties配置文件

    server.port=5555
    spring.application.name=api-gateway
    zuul.routes.api-a.path=/api-a/**
    #这里用serviceId代替url,用服务名代替ip+端口号
    zuul.routes.api-a.serviceId=hello-service
    eureka.client.service-url.defaultZOne=http://localhost:1111/eureka

    注意:zuul.routes.api-a.url=hello-service也能实现功能,但是它不能进行正常的负载均衡和容错保护。



  3. 测试,访问http://localhost:5555/api-a/hello

    访问成功。



 三、服务路由的默认规则

在面向服务的路由中,由于名字是随意起的,那么是不是可以这样:


zuul.routes.hello-service.path=/hello-service/**
zuul.routes.hello-service.serviceId=hello-service

名字就是服务名,其实在实际的应用中,我们往往就是这样命名的。如果有这样的规则的话,那Zuul就可以帮我们默认实现这样的功能,进一步省去了配置的麻烦。

我们来做个实验,将配置文件改为:


server.port=5555
spring.application.name=api-gateway
eureka.client.service-url.defaultZOne=http://localhost:1111/eureka

然后页面访问验证

访问成功。

 

但是由于默认情况下,Eureka上的服务都会被Zuul创建默认的映射关系来进行路由,使得我们不想对外开放的服务也被外部访问到,这个时候可以通过配置zuul.ignored-services来进行配置不需要自动创建路由的规则。当zuul.ignored-services=*的时候,所有的服务都不会自动创建路由规则,这个时候需要通过前面的配置进行相关路由配置了。

================华丽的分割线===================

前面说了那么多都是围绕一个问题展开的:路由规则和服务实例的维护问题,那么怎么解决第二个问题(校验冗余问题)呢?

 四、请求过滤

为了在API网关中实现对客户端请求的校验,我们可以通过过滤器来实现对请求的拦截和过滤,实现方法比较简单,只需要继承ZuulFilter抽象类并实现其四个方法就行了。

修改api-gateway:



  1. 新增过滤器类

    /**
    * 继承ZuulFilter,并且实现其4个接口
    *
    * 用来进行请求过滤
    *
    */
    public class AccessFilter extends ZuulFilter {
    Logger logger
    = LoggerFactory.getLogger(AccessFilter.class);
    /*
    * shouldFilter 判断该过滤器是否需要被执行
    *
    * 这里直接返回true,表示该过滤器对所有请求都会生效。
    * 实际运用中我们可以利用该函数指定过滤器的有效范围
    */
    @Override
    public boolean shouldFilter() {
    return true;
    }
    /*
    * 过滤器的具体逻辑
    *
    * 这里我们通过ctx.setSendZuulResponse(false)让zuul过来请求,不对其进行路由
    * 然后通过ctx.setResponseStatusCode(401)设置了返回的错误码
    *
    */
    @Override
    public Object run() {
    RequestContext context
    = RequestContext.getCurrentContext();
    HttpServletRequest request
    = context.getRequest();
    Object accessToken
    = request.getParameter("accessToken");

    logger.info(
    "send {} request to {}", request.getMethod(),request.getRequestURL().toString());
    if(accessToken == null) {
    context.setSendZuulResponse(
    false);
    context.setResponseStatusCode(
    401);
    }

    return null;
    }
    /* filterType 返回过滤器类型
    * 他决定了过滤器在请求的哪个生命周期中执行。这里定义为pre,代表会在请求被路由前执行。
    *
    * pre:请求执行之前filter
    * route: 处理请求,进行路由
    * post: 请求处理完成后执行的filter
    * error:出现错误时执行的filter
    */
    @Override
    public String filterType() {
    return "pre";
    }


    /*
    * filterOrder 返回过滤器的执行顺序
    *
    * 当请求在一个阶段有多个过滤器是,需要根据该方法的返回值来依次执行
    *
    */
    @Override
    public int filterOrder() {
    return 0;
    }
    }



  2. 修改启动类

    /**
    * @EnableZuulProxy 开启Zuul 的API网关服务功能
    *
    */
    @EnableZuulProxy
    @SpringCloudApplication
    public class GateWayApp {
    //追加bean的是实现
    @Bean
    public AccessFilter accessFilter() {
    return new AccessFilter();
    }

    public static void main(String[] args) {
    SpringApplication.run(GateWayApp.
    class, args);
    }
    }



  3. 测试


    1. )访问http://localhost:5555/hello-service/hello,访问失败

      1.  




    2. )访问http://localhost:5555/hello-service/hello?accessToken=token,正常访问

       



 

修改后的代码结构:

 

 五、拓展延伸

其实路由功能在真正运行时,他的路由映射和请求转发都是由几个不同的过滤器完成的。

路由映射主要通过pre类型的过滤器完成,他将请求路径与配置的路由规则进行匹配,找到需要转发的目标地址。

而请求转发的部分则是由route类型的过滤器完成的,对pre类型过滤器获取的路由地址进行转发。

所以,过滤器可以说是Zuul实现API网关功能最为核心的部件,每一个进入Zuul的HTTP请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。

 



推荐阅读
  • SOA架构理解理解SOA架构,了解ESB概念,明白SOA与微服务的区别和联系,了解SOA与热门技术的结合与应用。1、面向服务的架构SOASOA(ServiceOrien ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 2020年第十一届蓝桥杯决赛JAVA B G题“皮亚诺曲线距离“的个人题解目录
    本文是2020年第十一届蓝桥杯决赛JAVA B G题“皮亚诺曲线距离“的个人题解目录。文章介绍了皮亚诺曲线的概念和特点,并提供了计算皮亚诺曲线上两点距离的方法。通过给定的两个点的坐标,可以计算出它们之间沿着皮亚诺曲线走的最短距离。本文还提供了个人题解的目录,供读者参考。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • Java如何导入和导出Excel文件的方法和步骤详解
    本文详细介绍了在SpringBoot中使用Java导入和导出Excel文件的方法和步骤,包括添加操作Excel的依赖、自定义注解等。文章还提供了示例代码,并将代码上传至GitHub供访问。 ... [详细]
  • springboot启动不了_Spring Boot + MyBatis 多模块搭建教程
    作者:枫本非凡来源:www.cnblogs.comorzlinp9717399.html一、前言1、创建父工程最近公司项目准备开始重构,框 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  •     这里使用自己编译的hadoop-2.7.0版本部署在windows上,记得几年前,部署hadoop需要借助于cygwin,还需要开启ssh服务,最近发现,原来不需要借助cy ... [详细]
  • 熟练掌握Spring Cloud,终于成为Java工程师的面试门槛 ... [详细]
  • 说出来你可能不信,我用三天做了一个完整的项目
    Java在人工智能中能起到什么作用?作为编程语言中的扛把子,Java20多年稳定不倒,就在于它的稳定性,维护成本极低。这使得 ... [详细]
  • boot集成的邮箱 spring_spring boot集成mybatis(2) – 使用pagehelper实现分页
    章节SpringBoot介绍SpringBoot开发环境搭建(Eclipse)SpringBootHelloWorld(restful接口)例子spri ... [详细]
  • 用Python手把手教你搭建一个web框架-flask微框架!
    在之前的文章当中,小编已经教过大家怎么搭建一个Django框架,今天我们来探索另外的一种框架的搭建,这个框架就是web框架-flask微框架啦!首先我们带着以下的几个问题来阅读本文:1、flask ... [详细]
author-avatar
guan
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有