前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Cloud 入门教程7、服务网关(Zuul)

Spring Cloud 入门教程7、服务网关(Zuul)

作者头像
KenTalk
发布2018-09-11 11:37:16
1K0
发布2018-09-11 11:37:16
举报
文章被收录于专栏:Ken的杂谈Ken的杂谈

一、前言

1、什么是服务网关?

服务网关也就是API网关,服务网关可以作为服务的统一入口,提供身份校验、动态路由、负载均衡、安全管理、统计、监控、流量管理、灰度发布、压力测试等功能

服务网关/API网关并不是微服务体系所特有的,而是微服务流行起来之后,服务网关基本上成了微服务架构的标配。服务网关通常用于向客户端或者合作伙伴应用提供统一的服务接入方式,例如:App网关、开放平台(OpenAPI)等等。

2、什么是Zuul?

Zuul是Netflix开源的服务网关/API网关,提供动态路由、监控、弹性、安全性等功能。

Zuul is an edge service that provides dynamic routing, monitoring, resiliency, security, and more. Please view the wiki for usage, information, HOWTO, etc https://github.com/Netflix/zuul/wiki

Zuul+Eureka交互示意图

这里只列举了单个网关集群,实际上互联网公司通常会有多个网关集群,App网关、HTML5网关、OpenAPI网关等等

3、本篇环境信息

框架

版本

Spring Boot

2.0.0.RELEASE

Spring Cloud

Finchley.RELEASE

Zuul

1.3.1 (Spring Cloud-Finchley还没整合2.x版本)

JDK

1.8.x

4、准备工作

参考上一篇:https://cloud.tencent.com/developer/article/1333825

基于源码:https://github.com/ken-io/springcloud-course/tree/master/chapter-06

  • 准备Eureka Server、服务提供者

启动Eureka Server: http://localhost:8800

启动Test Service:http://localhost:8602,http://localhost:8603

二、服务网关:Zuul

1、创建Zuul项目

  • 创建项目

按照惯例,使用maven-archtype-quickstart模板创建项目

说明

GroupId

io.ken.springcloud.zuul

ArtifactId

zuul

  • 修改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>io.ken.springcloud.zuul</groupId>
    <artifactId>zuul</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>zuul</name>
    <url>http://ken.io</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

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

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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

2、配置Zuul启动类

修改\src\main\java\io\ken\springcloud\zuul\App.java

@EnableZuulProxy:启用Zuul

package io.ken.springcloud.zuul;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

3、配置Zuul

在\src\main下创建文件夹resources文件夹并设置为Resources Root

在resources文件夹下创建application.yml文件并配置Zuul

server:
  port: 8888

spring:
  application:
    name: zuul

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8800/eureka/

4、Zuul访问测试

启动zuul项目后,访问:http://localhost:8888/testservice

会交替显示以下信息

{
  "code": 0,
  "message": "hello",
  "content": null,
  "serviceName": "testservice",
  "host": "localhost:8602"
}
/*********分割线*********/
{
  "code": 0,
  "message": "hello",
  "content": null,
  "serviceName": "testservice",
  "host": "localhost:8603"
}
  • 解析

通过配置文件我们知道,Spring Cloud Zuul 将自己作为一个服务注册到了Eureka。这也就意味着Zuul可以拿到所有注册到Eureka的其他服务的信息。Zuul为这些服务创建了默认的路由规则:/{servicename}/**

所以,我们访问 http://localhost:8888/testservice

就相当于访问:(testservice)http://localhost:8602

由于我们注册了两个testservice的实例,而且Zuul本身具备负载均衡的功能。所以会交替显示不同实例的响应内容。

5、FeignClient访问Zuul

根据上一篇FeignClient项目代码调整

在\src\main\java\io\ken\springcloud\feignclient\service

增加TestServiceZuul.java

package io.ken.springcloud.feignclient.service;

import io.ken.springcloud.feignclient.model.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "zuul")
public interface TestServiceZuul {

    @RequestMapping(value = "/testservice/", method = RequestMethod.GET)
    String indexService();

    @RequestMapping(value = "/testservice/plus", method = RequestMethod.GET)
    Result plusService(@RequestParam(name = "numA") int numA, @RequestParam(name = "numB") int numB);
}

简单来说,就是将直接ServiceName配置为zuul,请求的url前增加目标服务的ServiceName即可。

引用示例:

@RestController
public class TestController {

    @Autowired
    private TestServiceZuul testServiceZuul;

    @RequestMapping("/ti-zuul")
    public Object ti_zuul() {
        return testServiceZuul.indexService();
    }

}

三、路由配置

1、路由配置参数说明

  • 路由配置基础参数说明

配置项

ken.io 的说明

zuul.routes.{routename}

路由名称,自定义,支持小写字母、-

zuul.routes.{routename}.path

要路由的路径,支持通配符:?、 、*

zuul.routes.{routename}.serviceId

注册在Eureka的ServiceName

zuul.routes.{routename}.url

如果应用没有注册在Eureka,也可以通过指定Url来路由

zuul.ignored-services

忽略指定的服务,可以配置多个,以,间隔

zuul.ignored-patterns

忽略指定的路径,可以配置多个,以,间隔。同样支持通配符

  • path通配符说明

通配符

说明

path举例

匹配示例

?

匹配单个任意字符

/ts/?

/ts/a、/ts/b

*

匹配任意字符

ts/*

/ts/a、/ts/b、/ts/ab

**

匹配任意字符且支持多级目录

ts/**

/ts/a、/ts/b、/ts/ab、/ts/ab/c

对于通配符来说,没有特定的需求,直接用**就好

2、路由配置示例

  • 路由到注册到Eureka的服务:testservice
zuul:
  routes:
    ts:
      path: /ts/**
      serviceId: testservice

通常适用于:一个服务随着业务的发展不断扩大需要拆分,这时候我们可以通过api兼容+路由配置来适配,可以对上游无感知。例如用户服务(userservice)有三个核心模块,auth、info、safe,经过拆分拆出来两个服务:authservice、safeservice。那么拆分后的路由配置:

zuul:
  routes:
    user-auth:
      path: /user/auth/**
      serviceId: authservice
    user-safe:
      path: /user/safe/**
      serviceId: safeservice
    user:
      path: /user/**
      serviceId: userservice

因为路由规则匹配顺序是按配置顺序来的,所以未拆出去的配置在最后。

  • 路由到指定站点

当一个应用并没有注册到服务注册中心(Eureka),我们又需要将它挂到网关上可以通过指定url的这种方式。

zuul:
  routes:
    ken-io:
      path: /ken/**
      url: https://ken.io/
  • 忽略指定路径

通常适用于某些通用的接口不暴露给外部,例如每个应用都会有一个健康检查入口,但是这个入口是不应该暴露给外部的,就可以通过忽略规则屏蔽掉。

zuul:
  ignored-patterns: /**/hs,/**/health
  • 忽略指定服务
zuul:
  ignored-services: aservice,bservice

四、Zuul过滤器

1、身份校验过滤器

  • 创建过滤器

在src\main\java\io\ken\springcloud\zuul创建package:filter

然后创建Filter类:AuthFilter.java

实现ZuulFilter并标记为Component

package io.ken.springcloud.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;


import javax.servlet.http.HttpServletRequest;
import java.util.logging.Logger;

@Component
public class AuthFilter extends ZuulFilter {

    private static Logger log = Logger.getLogger(AuthFilter.class.toString());

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("header-token:%s,param-token:%s", request.getHeader("token"), request.getParameter("token")));
        String token_header = request.getHeader("token") == null ? "" : request.getHeader("token");
        String token_param = request.getParameter("token") == null ? "" : request.getParameter("token");
        if (token_header.equals("") && token_param.equals("")) {
            try {
                ctx.setSendZuulResponse(false);
                ctx.getResponse().getWriter().write("{\"code\": 9999,\"message\": \"token is empty.\"}");
            } catch (Exception e) {
                log.warning("system error");
            }

        } else if (!token_header.equals("")) {
            log.warning(String.format("token is %s", token_header));
        } else if (!token_param.equals("")) {
            log.warning(String.format("token is %s", token_param));
        }
        return null;
    }
}

重新启动Zuul,然后访问:http://localhost:8888/testservice

由于缺少token,会返回如下信息:

{
  "code": 9999,
  "message": "token is empty."
}

这里只是做一个示例,需要完成身份校验,还要完善代码。

2、ZuulFilter使用说明

  • ZuulFilter方法说明

方法名

说明

filterType()

过滤器类型:pre、routing、post、error

filterOrder

过滤器顺序,用于指定过滤器执行顺序

shouldFilter

是否要过滤,可以根据当前请求信息判断是否过滤,也可以默认返回true

run

过滤器执行逻辑,执行具体的过滤操作。

  • FilterType说明

type

说明

pre

在路由之前执行过滤

routing

在路由时执行过滤

post

在路由之后执行过滤

error

在发生错误时执行过滤

五、备注

  • 本篇代码示例

https://github.com/ken-io/springcloud-course/tree/master/chapter-07

  • 本篇参考

https://eacdy.gitbooks.io/spring-cloud-book/content/2%20Spring%20Cloud/2.6%20API%20Gateway.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-07-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
    • 1、什么是服务网关?
      • 2、什么是Zuul?
        • 3、本篇环境信息
          • 4、准备工作
          • 二、服务网关:Zuul
            • 1、创建Zuul项目
              • 2、配置Zuul启动类
                • 3、配置Zuul
                  • 4、Zuul访问测试
                    • 5、FeignClient访问Zuul
                    • 三、路由配置
                      • 1、路由配置参数说明
                        • 2、路由配置示例
                        • 四、Zuul过滤器
                          • 1、身份校验过滤器
                            • 2、ZuulFilter使用说明
                            • 五、备注
                            相关产品与服务
                            负载均衡
                            负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档