沉梦手记 沉梦手记
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 数据库基础
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • 网络通信
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 前端环境搭建
  • HTML与CSS
  • JS学习
  • Axios入门
  • Vue Router入门
  • Pinia入门
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 运维与部署
  • 音视频处理
  • 随笔
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
  • 脚手架搭建
  • 瑞吉外卖
  • 黑马点评
  • vue-blog
  • 沉梦接口开放平台
  • 用户中心
  • 聚合搜索平台
  • 仿12306项目
  • 壁纸小程序项目
  • RuoYi-Vue
Github (opens new window)

沉梦听雨

时间是最好的浸渍剂,而沉淀是最好的提纯器🚀
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 数据库基础
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • 网络通信
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 前端环境搭建
  • HTML与CSS
  • JS学习
  • Axios入门
  • Vue Router入门
  • Pinia入门
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 运维与部署
  • 音视频处理
  • 随笔
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
  • 脚手架搭建
  • 瑞吉外卖
  • 黑马点评
  • vue-blog
  • 沉梦接口开放平台
  • 用户中心
  • 聚合搜索平台
  • 仿12306项目
  • 壁纸小程序项目
  • RuoYi-Vue
Github (opens new window)
  • 脚手架搭建
  • 瑞吉外卖

  • 黑马点评

  • vue-blog

  • 沉梦接口开放平台

    • 项目概述与设计
    • 接口管理与SDK开发
    • 接口发布与在线调用
    • 调用统计与API网关
      • 第四阶段
        • 主要内容
        • 接口调用次数统计
        • 问题
        • 网关
        • 网关作用
        • 路由
        • 负载均衡
        • 统一鉴权
        • 统一处理跨域
        • 统一业务处理
        • 访问控制
        • 发布控制
        • 流量染色
        • 统一接口保护
        • 统一日志
        • 统一文档
        • 网关的分类
        • 网关实现
        • Spring Cloud Gateway 用法
        • 核心概念
        • 两种配置方式
        • 建议开启日志
        • 断言
        • 过滤器
      • 第五阶段
        • 主要内容
        • 要用到的特性
        • 业务逻辑
        • 具体实现
        • 1、请求转发
        • 2、编写业务逻辑
        • 问题
    • RPC与Dubbo
    • 笔记
    • 项目技术亮点
  • 用户中心

  • 聚合搜索平台

  • 仿12306项目

  • 壁纸小程序项目

  • RuoYi-Vue

  • 项目笔记
  • 沉梦接口开放平台
沉梦听雨
2023-06-08
目录

调用统计与API网关

# 调用统计与 API 网关

# 第四阶段

# 主要内容

  1. 开发接口调用次数统计功能
  2. 优化整个系统的架构 —— API 网关详解
    • 网关是什么?
    • 网关的作用?
    • 网关的应用场景及实现?
    • 结合业务去应用网关

# 接口调用次数统计

需求:

  1. 用户每次调用接口成功,次数 +1(可以考虑用 -1)
  2. 给用户分配或者用户自主申请接口调用次数

业务流程:

  1. 用户调用接口(之前已完成)
  2. 修改数据库,调用次数 +1

设计库表:

用哪个用户?哪个接口?

用户 => 接口(多对多)

用户调用接口关系表:

-- 用户调用接口关系表
create table if not exists cmapi.`user_interface_info`
(
    `id` bigint not null auto_increment comment '主键' primary key,
    `userId` bigint not null comment '调用用户 id',
    `interfaceInfoId` bigint not null comment '接口 id',
    `totalNum` int default 0 not null comment '总调用次数',
    `leftNum` int default 0 not null comment '剩余调用次数',
    `status` int default 0 not null comment '0-正常,1-禁用',
    `createTime` datetime default CURRENT_TIMESTAMP not null comment '创建时间',
    `updateTime` datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
    `isDelete` tinyint default 0 not null comment '是否删除(0-未删,1-已删)'
) comment '用户调用接口关系';
1
2
3
4
5
6
7
8
9
10
11
12
13

开发步骤:

  1. 开发基本增删改查(给管理员用)
  2. 开发用户调用接口次数 +1 的功能(service)

# 问题

如果每个接口的方法都调用次数 +1,是不是比较麻烦?

致命问题: 接口开发者需要自己去添加统计代码。

image-20230506174904962

  • 使用 AOP 切面的优点: 独立于接口,在每个接口调用后统计次数 +1
  • 使用 AOP 切面的缺点: 只存在于单个项目中,如果每个团队都要开发自己模拟接口,那么都要写一个切面

# 网关

什么是网关?理解成火车站的检票口,统一去检票。

# 网关作用

统一去进行一些操作、处理一些问题。比如:

  1. 路由
  2. 负载均衡
  3. 统一鉴权
  4. 跨域
  5. 统一业务处理(缓存也在这里处理)
  6. 访问控制
  7. 发布控制
  8. 流量染色
  9. 接口保护
    • 限制请求
    • 信息脱敏(操作请求头,响应头)
    • 降级(熔断)—— 请求某个接口时不成功,提示请求其它接口,兜底效果
    • 限流:学习令牌桶算法、学习漏桶算法,学习一下 RedisLimitHandler
    • 超时时间
  10. 统一日志
  11. 统一文档
# 路由

起到转发的作用,比如有接口 A 和接口 B,网关会记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口(服务器/集群)。

/a => 接口 A
/b => 接口 B
1
2

参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

# 负载均衡

在路由的基础上:

/c => 服务A/集群A(随机转发到其中的某一机器)
1

uri 从固定地址改成 lb:xxxx。

# 统一鉴权

判断用户是否有权限进行操作,无论访问什么接口,都统一去判断权限,不用重复写。

# 统一处理跨域

网关统一处理跨域,不用在每个项目里单独处理。

参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration

# 统一业务处理

把每个项目中都要做的通用逻辑放到上层(网关),统一处理,比如本项目的次数统计。

# 访问控制

黑白名单,比如限制 DDOS IP。

# 发布控制

灰度发布,比如上线新接口,先给新接口分配 20% 的流量,老接口 80%,再慢慢调整比重。(不同人的软件最新版不一样)

参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-weight-route-predicate-factory

# 流量染色

给请求(流量)添加一些标识,一般是设置请求头中,添加新的请求头。

  • 添加请求头:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-addrequestheader-gatewayfilter-factory
  • 全局染色:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#default-filters
# 统一接口保护
  1. 限制请求:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#requestheadersiz-gatewayfilter-factory
  2. 信息脱敏:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-removerequestheader-gatewayfilter-factory
  3. 降级(熔断) 进行兜底:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#fallback-headers
  4. 限流:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-requestratelimiter-gatewayfilter-factory
  5. 超时时间 超时就中断:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#http-timeouts-configuration
  6. 重试(业务保护):https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-retry-gatewayfilter-factory
# 统一日志

统一的请求、响应信息记录。

# 统一文档

将下游项目的文档进行聚合,在一个页面统一查看。

建议用:https://doc.xiaominfo.com/docs/middleware-sources/aggregation-introduction

# 网关的分类

  • 全局网关(接入层网关):作用是负载均衡、请求日志等,不和业务逻辑绑定
  • 业务网关(微服务网关):会有一些业务逻辑,作用是将请求转发到不同的业务/项目/接口/服务

参考文章:https://blog.csdn.net/qq_21040559/article/details/122961395

# 网关实现

  1. Nginx(全局网关)、Kong 网关(API 网关),编程成本相对较高
  2. Spring Cloud Gateway(取代了 Zuul),性能高,可以用 Java 代码来写逻辑,适于学习

网关技术选型:https://zhuanlan.zhihu.com/p/500587132

# Spring Cloud Gateway 用法

全部内容基本来自官网:

  • 官网:https://spring.io/projects/spring-cloud-gateway
  • 官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

# 核心概念

概念 说明
路由 Route 根据什么条件,转发请求到哪里
断言 Predicate 一组规则、条件,用来确定如何转发路由
过滤器 Filter 对请求进行一系列的处理,比如添加请求头、添加请求参数

请求流程:

  1. 客户端发起请求
  2. Handler Mapping:根据断言,去将请求转发到对应的路由
  3. Web Handler:处理请求(一层层经过过滤器)
  4. 实际调用服务

image-20230509171132036

# 两种配置方式

1. 配置式(声明式,方便、规范)

简化版:

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - Cookie=mycookie,mycookievalue
1
2
3
4
5
6
7
8

完整版:

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - name: Cookie
          args:
            name: mycookie
            regexp: mycookievalue
1
2
3
4
5
6
7
8
9
10
11

2. 编程式(灵活、相对麻烦)

# 建议开启日志

logging:
  level:
    org:
      springframework:
        cloud:
          gateway: trace
1
2
3
4
5
6

# 断言

官网地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

目录:

  1. After —— 在 xx 时间之后
  2. Before —— 在 xx 时间之前
  3. Between —— 在 xx 时间之间
  4. 请求类别
  5. 请求头(包含 Cookie)
  6. 查询参数
  7. 客户端地址
  8. 权重

The After Route Predicate Factory

当前时间在这个时间之后,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]
1
2
3
4
5
6
7
8

The Before Route Predicate Factory

当前时间在这个时间之前,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
1
2
3
4
5
6
7
8

The Between Route Predicate Factory

当前时间在这个时间之间,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: https://example.org
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
1
2
3
4
5
6
7
8

The Cookie Route Predicate Factory

如果你的请求头 cookie 的是 chocolate,它的值是 ch.p,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p
1
2
3
4
5
6
7
8

The Header Route Predicate Factory

如果你的请求头包含 X-Request-Id 这样一个请求头,并且它的值符合正则表达式的规则,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+
1
2
3
4
5
6
7
8

The Host Route Predicate Factory

如果你的访问的是这个 **.somehost.org, **.anotherhost.org 域名,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org
1
2
3
4
5
6
7
8

The Method Route Predicate Factory

如果你的请求类别是 GET、POST,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST
1
2
3
4
5
6
7
8

The Path Route Predicate Factory

如果你的访问的地址是以 /red/{segment}, /blue/{segment} 路径作为前缀,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}
1
2
3
4
5
6
7
8

The Query Route Predicate Factory

根据查询条件,比如 red 匹配 gree.,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree.
1
2
3
4
5
6
7
8

The RemoteAddr Route Predicate Factory

根据远程地址,比如你的用户的 ip 地址是 192.168.1.1/24,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24
1
2
3
4
5
6
7
8

The Weight Route Predicate Factory

根据你设置的权重,给你把同一个访问的地址,重定向到不同的服务,轻松实现发布控制。

spring:
  cloud:
    gateway:
      routes:
      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
        - Weight=group1, 2
1
2
3
4
5
6
7
8
9
10
11
12

The XForwarded Remote Addr Route Predicate Factory

从请求头中如果拿到 XForwarded 这个请求头的地址 192.168.1.1/24,就会访问当前这个路由。

spring:
  cloud:
    gateway:
      routes:
      - id: xforwarded_remoteaddr_route
        uri: https://example.org
        predicates:
        - XForwardedRemoteAddr=192.168.1.1/24
1
2
3
4
5
6
7
8

# 过滤器

官网文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

基本功能:对请求头、请求参数、响应头的增删改查。

  1. 添加请求头
  2. 添加请求参数
  3. 添加响应头
  4. 降级
  5. 限流
  6. 重试

引入依赖(用于集成 Reactor Resilience4j 断路器库,以实现微服务的容错处理和服务熔断(接口保护 —— 降级)等功能):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
1
2
3
4

小作业:

通过阅读源码:https://spring.io/projects/spring-cloud-gateway/#samples 来了解 gateway 编程式开发。

# 第五阶段

# 主要内容

  1. 实现统一的接口鉴权和计费(API 网关实践)

实现统一的用户鉴权,统一的接口调用次数统计(把 API 网关用到项目中)。

# 要用到的特性

  1. 路由(转发请求到模拟接口项目)
  2. 负载均衡(需要用到注册中心)
  3. 统一鉴权(accessKey、secretKey)
  4. 统一处理跨域
  5. 统一业务处理(每次请求接口后,接口调用次数 +1)
  6. 访问控制(黑白名单)
  7. 发布控制
  8. 流量染色(记录请求是否为网关来的)
  9. 统一接口保护
    1. 限制请求
    2. 信息脱敏
    3. 降级(熔断)
    4. 限流(学习令牌桶算法、学习漏桶算法,学习一下 RedisLimitHandler)
    5. 超时时间
    6. 重试(业务保护)
  10. 统一日志(记录每次的请求和响应)
  11. 统一文档

# 业务逻辑

  1. 用户发送请求到 API 网关

    面试官可能会问:为什么要用 API 网关?可以联想一下上面那个画图过程。

  2. 请求日志
  3. (黑白名单)
  4. 用户鉴权(判断 ak、sk 是否合法)
  5. 请求的模拟接口是否存在?
  6. 请求转发,调用模拟接口
  7. 响应日志
  8. 调用成功,接口调用次数 +1
  9. 调用失败,返回一个规范的错误码

# 具体实现

# 1、请求转发

使用 Path 前缀匹配断言:

将所有前缀为 /api/ 的请求进行转发,转发到 http://localhost:8123/api。

比如请求网关 localhost:8090/api/name/张三,转发到 localhost:8123/api/name/张三。

server:
  port: 8090

spring:
  cloud:
    gateway:
      routes:
        - id: api_route
          # 设置转发到哪个网址
          uri: http://localhost:8123
          # 前缀断言
          predicates:
            - Path=/api/**
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2、编写业务逻辑

使用了 GlobalFilter(编程式,还有一种叫配置式,上面有讲),全局请求拦截处理(类似 AOP)。

官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters

因为网关项目没引入 MyBatis 等操作数据库的类库,如果该操作较为复杂,可以由 backend 增删改查项目提供接口,我们直接调用,不用重复写逻辑了。

  • HTTP 请求(用 HTTPClient、用 RestTemplate、Feign)
  • RPC(Dubbo)

# 问题

预期等模拟接口调用完成,才记录响应日志、统计调用次数。

但现实是 chain.filter 方法立刻返回了,直到 filter 过滤器 return 后(此时已经记录了响应日志)才调用了模拟接口。

原因是: chain.filter 是个异步操作,理解为前端的 promise。

解决方案: 利用 response 装饰者,增强原有 response 的处理能力。

参考博客:https://blog.csdn.net/qq_19636353/article/details/126759522(以这个为主)

其他参考:

  • 网关 在 GlobalFilter 拿出返回数据 response (opens new window)
  • SpringCloud-Gateway 统一处理返回参数 (opens new window)
  • 对请求参数解密,返回参数加密处理_springcloud 针对全局返回报文加密 (opens new window)
上次更新: 2026/10/10 17:43:40
接口发布与在线调用
RPC与Dubbo

← 接口发布与在线调用 RPC与Dubbo→

Theme by Vdoing | Copyright © 2023-2026 沉梦听雨 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式