SpringCloud Finchley 实战入门(基于springBoot 2.0.3)【九 zuul 微服务网关配置】

简介: 网关介绍API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。

网关介绍

API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。它除了要实现请求路由、 负载均衡、 校验过滤等功能之外,还需要更多能力,比如与服务治理框架的结合、请求转发时的熔断机制、服务的聚合等一系列高级功能。

入门例子

创建一个moudle,命名为eureka-zuul,创建时选择一些的组件依赖:


img_dca2630fbff0b6925eea7126fb14fbb5.png
1533108772510.png

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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>eureka-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-zuul</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

配置application.yml

server:
  port: 1100
spring:
  application:
    name: service-zuul

application.yml只是设置基本信息,结合之前创建的配置中心,我们把主要把配置的主要信息通过eureka-config-git配置中心获取。所以添加一个bootstrap.yml配置文件。

spring:
  cloud:
    config:
      profile: dev #dev开发环境配置文件,test测试环境配置文件,pro正式环境文件
      label: master #git仓库对应的分支名称 config-label-test
#      label: config-label-test #git仓库对应的分支名称 config-label-test
#      uri: http://localhost:7001/ #config-server
      name: service-zuul
      discovery:
        serviceId: config-server-git #基于服务注册发现的方式查找
        enabled: true
eureka:
  client:
      serviceUrl:
        defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
management: #配置暴露监控节点地址
  endpoints:
    web:
      exposure:
        include: "*"
      cors:
        allowed-origins: "*"
        allowed-methods: "*"
#注册中心eureka.client.service-url.defaultZone = 一定要放在boostrap文件中,不然启动会报错

这里的配置主要就是指向配置中心。

项目的主类添加EnableZuulProxy注解

/*@SpringBootApplication
EnableEurekaClient*/
@EnableZuulProxy//注解@EnableZuulProxy以开启zuul特性
@SpringCloudApplication //使用@SpringCloudApplication包括,
// Springboot注解,注册服务到注册中心注解,熔断器注解
// 在SpringCloud看来这是每一微服务所必须应有的三个注解,所以才推出了@SpringCloudApplication注解
public class EurekaZuulApplication {

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

另外config-repo这个配置文件中心的项目有个zuul的配置文件bootstrap.yml主要配置的就是指向了这个config-repo的配置文件。
service-zuul-dev.yml

zuul:
  ignoredServices: '*' #忽略所有未配置的service,每一个微服务的路由配置都需要配置
  host:
    connect-timeout-millis: 20000
    socket-timeout-millis: 20000
  routes:
    ribbon-service: #自定义名称
      path: /ribbon/**
      serviceId: service-user-ribbon #/ribbon/开头的路径转发至service-user-ribbon微服务
      sensitiveHeaders: true #springcloud项目中经过网关zuul转发请求后发生session失效问题,这是由于zuul默认会丢弃原来的session并生成新的session
      #所以这里对制定的路由开启自定义敏感头。除了设置为true,也可以设置为空。zuul.sensitiveHeaders= 只是全局设置的做法。不推荐!破坏了默认设置的用意
hystrix: #hystrix配置
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2500
ribbon: #ribbon负载均衡参数配置
  ReadTimeout: 5000
  ConnectTimeout: 5000
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/

相关的配置注释已经说得很清楚了

接下来我们新建一个类来测试zuul功能。
创建一个UserFallbackProvider类实现FallbackProvider接口


@Component
public class UserFallbackProvider implements FallbackProvider {

    @Override
    public String getRoute() {
        return "service-user-ribbon";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return 200;
            }

            @Override
            public String getStatusText() throws IOException {
                return "OK";
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("fallback".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}
img_280150dbec721e90d55d6c3b1f17ce70.png
1533110129632.png

依次启动服务注册中心=>configGit=>serviceUser=>serviceUserRibbon=>zuul


img_97ba0658190d1d9818368c3a9502d609.png
1533110998412.png

img_621e837619e770bf5d841a68aaf4f4ef.png
1533110900002.png

img_b1ed68f5fb12f9bbe869eb1a5405ab70.png
1533111016759.png

服务确保正常,我们访问zuul的服务地址:http://localhost:1100/ribbon/listUsersByRibbon

img_eaf372f3aa6d28091366f405716b3b60.png
1533111048541.png

数据正常返回,说明zuul项目配置正常。

过滤器

上面的演示是用zuul实现一个基本的接口请映射请求,zuul主要的主要是认证和鉴权这方面的功能。我们下面实现一个过滤器的功能;在上面的项目基础上,我们新建一个过滤器AccessFilter实现ZuulFilter接口

@Log
public class AccessFilter extends ZuulFilter {
    @Override
    public String filterType() {
        /**
         * pre 代表请求被路由前执行
         */
        return "pre";
    }

    @Override
    public int filterOrder() {
        /**
         * 过滤器执行的顺序
         */
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        /**
         * 判断过滤器是否执行
         */
        return true;
    }

    /**
     * 具体的过滤逻辑
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        log.info("send " + request.getMethod() + " Request to " + request.getRequestURL().toString());
        String token = request.getParameter("token");
        if (StringUtils.isBlank(token)) {
            log.warning("access token is empty");
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseStatusCode(401);
            try {
                HttpServletResponse response = currentContext.getResponse();
                response.setCharacterEncoding("utf-8");  //设置字符集
                response.setContentType("text/html; charset=utf-8"); //设置相应格式
                response.getWriter().write("token 验证失败");
            } catch (IOException e) {
                log.info("response io异常");
                e.printStackTrace();
            }
            return null;
        }
        return null;
    }
}

这里的过滤器主要的作用是拦截请求,然后从请求体中获取参数token。判断有没有token这个参数,如果有的话,就通过;如果获取不到token参数,就直接响应一个401的状态。
然后在项目的主类中注入该过滤器:

/**
     * 启用过滤器功能
     *
     * @return
     */
    @Bean
    public AccessFilter accessFilter() {
        return new AccessFilter();
    }

重启zuul服务,重新访问地址:http://localhost:1100/ribbon/listUsersByRibbon
当我们没有在请求地址中加上token的参数时,该接口响应token校验失败了。

img_37d9050d6a3dab1441648a9ac6b1371a.png
1533111845622.png

我们在通过地址http://localhost:1100/ribbon/listUsersByRibbon?token=token
在加上token参数的情况下,过滤器校验通过就可以正常的响应接口了。

img_17dff9ccda89bd9883902f1ade90ac90.png
1533111890497.png

github 项目源码

目录
相关文章
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
607 0
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
459 0
|
NoSQL Java 关系型数据库
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
本文介绍在 Spring Boot 中集成 Redis 的方法。Redis 是一种支持多种数据结构的非关系型数据库(NoSQL),具备高并发、高性能和灵活扩展的特点,适用于缓存、实时数据分析等场景。其数据以键值对形式存储,支持字符串、哈希、列表、集合等类型。通过将 Redis 与 Mysql 集群结合使用,可实现数据同步,提升系统稳定性。例如,在网站架构中优先从 Redis 获取数据,故障时回退至 Mysql,确保服务不中断。
440 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
|
Java 数据安全/隐私保护 微服务
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——Spring Boot中自定义事件监听
本文介绍了在Spring Boot中实现自定义事件监听的完整流程。首先通过继承`ApplicationEvent`创建自定义事件,例如包含用户数据的`MyEvent`。接着,实现`ApplicationListener`接口构建监听器,用于捕获并处理事件。最后,在服务层通过`ApplicationContext`发布事件,触发监听器执行相应逻辑。文章结合微服务场景,展示了如何在微服务A处理完逻辑后通知微服务B,具有很强的实战意义。
666 0
|
缓存 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——监听器介绍和使用
本文介绍了在Spring Boot中使用监听器的方法。首先讲解了Web监听器的概念,即通过监听特定事件(如ServletContext、HttpSession和ServletRequest的创建与销毁)实现监控和处理逻辑。接着详细说明了三种实际应用场景:1) 监听Servlet上下文对象以初始化缓存数据;2) 监听HTTP会话Session对象统计在线用户数;3) 监听客户端请求的Servlet Request对象获取访问信息。每种场景均配有代码示例,帮助开发者理解并应用监听器功能。
676 0
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
352 0
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
1659 0
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——事务相关
本文介绍Spring Boot事务配置管理,阐述事务在企业应用开发中的重要性。事务确保数据操作可靠,任一异常均可回滚至初始状态,如转账、购票等场景需全流程执行成功才算完成。同时,事务管理在Spring Boot的service层广泛应用,但根据实际需求也可能存在无需事务的情况,例如独立数据插入操作。
318 0
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
812 0
|
消息中间件 存储 Java
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装
本教程介绍ActiveMQ的安装与基本使用。首先从官网下载apache-activemq-5.15.3版本,解压后即可完成安装,非常便捷。启动时进入解压目录下的bin文件夹,根据系统选择win32或win64,运行activemq.bat启动服务。通过浏览器访问`http://127.0.0.1:8161/admin/`可进入管理界面,默认用户名密码为admin/admin。ActiveMQ支持两种消息模式:点对点(Queue)和发布/订阅(Topic)。前者确保每条消息仅被一个消费者消费,后者允许多个消费者同时接收相同消息。
462 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装