『造轮子』亿级短URL生成器的架构设计及源码分享

news2024/12/28 20:21:09

请添加图片描述
📣读完这篇文章里你能收获到

  • 了解博主的短链生成的架构设计思路
  • 学习不同的短链技术方案选择
  • 学习基于混淆的自增短URL算法
  • 了解博主造的轮子SuperShortLink短链开源项目
  • 感谢点赞+收藏,避免下次找不到~

请添加图片描述

文章目录

  • 一、需求分析
    • 1. 短链生成及访问需求
    • 2. 短链应用授权管理需求
    • 3. 非功能性需求
  • 二、概要设计
    • 1. 短链服务用例图
    • 2. 整体部署模型
    • 3. 领域设计
    • 4. 短链生成技术方案选择
      • 4.1 单项散列函数生成短 URL
      • 4.2 预生成短 URL
      • 4.3 基于混淆的自增短 URL
  • 三、详细设计
    • 1. 混淆自增算法详解
      • 1.1 混淆加密算法设计
      • 1.2 恢复混淆解密算法设计
      • 1.3 算法量级支撑
    • 2. 重定向响应码
    • 3. 高并发挑战方案
    • 4. API授权校验
  • 四、Web管理后台
  • 五、项目源码
  • 六、思考

请添加图片描述

一、需求分析

1. 短链生成及访问需求

短 URL 生成器,也称作短链接生成器,就是将一个比较长的 URL 生成一个比较短的URL,当浏览器通过短 URL 生成器访问这个短 URL 的时候,重定向访问到原始的长 URL目标服务器,访问时序图如下:
生成短链时序图.png
用户访问短URL时序描述:

  1. 由应用调用短链服务生成短 URL,并将该短URL 展示给用户
  2. 用户在浏览器中点击该短 URL 的时候,请求发送到短 URL 生成器
  3. 短URL 生成器返回 HTTP 重定向响应,将用户请求重定向到最初的原始长 URL
  4. 浏览器访问长 URL 服务器,完成请求服务

2. 短链应用授权管理需求

短链管理,短链系统管理员可以在管理后台做以下操作:

  • 查看已生成的短链列表以及短链的访问次数统计
  • 直接在线输入长URL生成短URL
  • 管理短链系统的授权秘钥(只有已授权的应用才可通过HTTP请求生成短链)

秘钥使用时序图如下:
配置秘钥时序图.png

秘钥使用流程描述:

  1. 由管理员在管理后台创建应用秘钥
  2. 将秘钥配到应用程序中
  3. 应用程序携带秘钥加密后的Token信息请求短链服务生成短URL
  4. 短链服务接收到请求时校验Token是否合法,合法则返回相应的短URL

3. 非功能性需求

  1. 系统需要保持高可用,不因单一服务器宕机而引起服务失效,即需保证服务是支持伸缩的
  2. 短 URL 应该是不可猜测的,即不能猜测某个短 URL 是否存在,也不能猜测短 URL 可能对应的长 URL 地址内容

请添加图片描述

二、概要设计

概要设计阶段主要关注短链服务的用例、部署模型、领域设计及短链生成方案的选择

1. 短链服务用例图

短链用例图(1).png

  1. 用户可以访问短URL,短链服务会将请求进行重定向
  2. 应用程序可以通过短链服务为长URL生成唯一的短URL
  3. 应用程序可以存储,统计分析短URL的相关数据,比如访问次数
  4. 管理员可以在Web后台检索、查看短链的生成及使用情况
  5. 管理员可以在Web后台管理授权访问的应用秘钥

2. 整体部署模型

短链服务的业务逻辑比较简单,相对比较有挑战的就是高并发的短URL的访问请求如何处理。高并发访问主要通过负载均衡与缓存解决。具体的架构图如下:
短链部署模型(2).png

3. 领域设计

领域设计这块分为两部分,一部分是短链生成记录,另一部分是应用授权
领域设计.png

4. 短链生成技术方案选择

短 URL 生成器的设计核心就是短 URL 的生成,即长 URL 通过某种函数,计算得到n个字符的短 URL。短 URL 有几种不同的生成算法。由于Base64后面两位的“+”和“/”在 URL 中会被编码为“%2B”以及“%2F”,需要进行再编码,因此不考虑后两位符号,下文皆以Base62编码([A-Z],[a-z],[0-9])作为描述

4.1 单项散列函数生成短 URL

散列函数可以将任意长度的输入(又叫做预映射, pre-image),通过执行复杂的运算,变成固定长度的输出又叫散列值, hash value)。在短URL生成中,散列函数可用于将长URL映射到短URL,从而达到缩短URL的效果。
通常的设计方案:

  1. 将长URL作为散列函数的输入
  2. 执行散列函数(MD5 或者 SHA256),将长URL转换为固定长度的哈希值
  3. 将哈希值进行进一步处理,进行Base62编码,防止冲突
  4. 将编码后的字符串截取N个字符作为短URL

具体流程如图:
单向散列生成流程(3).png

  • 优点:生成速度快
  • 缺点:存在哈希碰撞,相同的哈希值对应不同的长URL,需要进行特殊处理以避免这一问题。虽然哈希碰撞的概率极低,但是 Base62 编码后再截断的 N 个字符有可能会冲突的概率就很高了。所以在生成的时候,需要先校验该短 URL 是否已经映射为其他的长 URL,如果是,那么需要重新计算(换单向散列算法,或者换 Base62 编码截断位置)。重新计算得到的短 URL 依然可能冲突,需要再重新计算

这样的冲突处理需要多次到存储中查找 URL,无法保证短链服务的性能要求,不考虑该方案

4.2 预生成短 URL

预生成短URL是指提前生成一些短URL并保存到数据库中,当用户需要缩短长URL时,直接从数据库中获取一个未被使用过的短URL,而不是现场生成新的短URL。
通常的设计方案:

  1. 采用随机算法离线预生成一批短URL,为了避免短URL冲突,每次生成的时候都需要检查该URL是否已存在
  2. 将预生成的短URL存到数据库
  3. 从数据库的短URL池中取一部分放到缓存中
  4. 当用户需要缩短一个长URL时,缓存中获取一个短URL
  5. 当缓存中的短URL快用完时,需从数据库再加载一部分到缓存中
  6. 当数据库中的预生成短URL快用完时,需要生成更多的短URL并添加到数据库中

具体流程如图:

单向散列生成流程(2).png

  • 优点:由于生成URL是离线计算,不会对服务器性能产生过大的负担,使用的时候读取短URL速度快
  • 缺点:预生成短 URL 会生成大量未被使用的短URL,浪费了存储空间和资源。此外,如果预生成的短URL数量不足,用户可能需要等待新的短URL被生成才能完成操作。越到后期随机算法生成的URL产生冲突的概率会越大,导致需要对比的次数越多

由于需要提前占用大量的存储空间,所以暂不考虑该方案

4.3 基于混淆的自增短 URL

自增短 URL 一种免冲突的算法是用自增长自然数来实现,即维持一个自增长的二进制自然数,然后将该自然数进行 Base62 编码即可得到一系列的短 URL。这样生成的的短 URL 必然唯一,通常采用自增序列号的方式进行生成。原理是将每一个长链接映射到一个唯一的自增序列号,然后将自增序列号转换为指定长度的短链接
比如:

  • 自然数 1 的常规Base62 编码是字符“B”
  • 就可以用 http://1.cn/B 作为短 URL。

弊端:但是这种算法将导致短URL是可猜测的,只要知道了其中一个短 URL,就可以猜测下一个短 URL


为了解决上述问题,基于上面的方式在生成时加入随机打乱编码Base62等混淆方法,可以增加被预测的概率,增强短URL的安全性
通常的设计方案:

  1. 初始化一个计数器,用于记录已经生成的短URL数量
  2. 当用户输入长URL时,将计数器自增1,并将自增后的值前面补0,比如自然数1变成0001
  3. 然后将该值倒转,也就是0001变成1000
  4. 为了防止短URL被预测,对转换后的Base62编码进行打乱或加密,以作混淆
  5. 将倒转后的值转换为混淆加密后的Base62编码,得到短URL

具体流程如图:
混淆自增短URL生成流程.png

  • 优点:编码保证绝对唯一,不会出现碰撞冲突,生成速度较快,不需要提前占用存储空间
  • 缺点:该方法需要维护一个计数器,如果生成短URL的并发量较大,性能瓶颈取决于计数器,计数器常见的方案:
    • Redis原子自增
    • 数据库自增主键

我们就是采用了基于混淆的自增短URL,计数器避免引入过多的中间件,因此选择了数据库自增主键

请添加图片描述

三、详细设计

在详细设计阶段,主要考虑重定向码、高并发场景应对方案、混淆加解密算法的解析及API授权校验的流程

1. 混淆自增算法详解

  • 标准Base64编码表如下:

image.png
其中“+”和“/”在 URL 中会被编码为“%2B”以及“%2F”,需要进行再编码,因此直接使用标准 Base64 编码进行短URL 编码并不合适,所以,我们需要针对 URL 场景对 Base64 编码进行改造,Base64 编码表中的 62,63 进行编码移除,更新为Base62编码

1.1 混淆加密算法设计

混淆加密算法过程.png

  1. 将标准编码随机打乱 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789

举例:打乱成:s9LFkgy5RovixI1aOf8UhdY3r4DMplQZJXPqebE0WSjBn7wVzmN2Gc6THCAKhaut

  1. 6位长度标准编码与打乱后编码的对应关系
计数器自增Id标准Base62编码标准Base62编码(6位字符)打乱后Base62编码打乱Base62编码(6位字符)
6GAAAAAGysssssy
66BEAAAABE9kssss9k
100BmAAAABm9Essss9E

可以看出,虽然打乱了,但还顺序性还是很明显

  1. 将前面补0再倒转,由于6位长度最大11位,为了避免倒转后超过该数值,因此补到10位
计数器自增Id打乱后Base62编码(6位字符)前面补0到10位倒转数字倒转后的打乱Base62编码(6位字符)
6sssssy00000000066000000000yPFrgP
66ssss9k000000006666000000005xWCQH
100ssss9E000000010010000000ssSKph

1.2 恢复混淆解密算法设计

恢复混淆解密算法过程(1).png
将请求收到的短链Key根据打乱后的Base62编码转成十进制数,补0到10位,然后倒转就得到原来的短链Id

短链Key解析后的十进制数前面补0到10位倒转数字
yPFrgP600000000060000000006
5xWCQH6600000000660000000066
ssSKph100000000010000000100

1.3 算法量级支撑

短链长度最大支持数数据量级
599999999亿
69999999999百亿
7999999999999万亿

2. 重定向响应码

满足短 URL 重定向要求的 HTTP 重定向响应码有 301 和 302 两种

  • 301 表示永久重定向,即浏览器一旦访问过该短 URL,就将重定向的原始长 URL 缓存在本地,此后不再请求短 URL 生成器,直接根据缓存在浏览器(HTTP 客户端)的长 URL 路径进行访问
  • 302 表示临时重定向,每次访问短 URL 都需要访问短 URL 生成器

一般来说,使用 301 状态码可以降低短链服务器的负载压力,但无法统计短 URL 的使用情况,而短链服务的架构设计完全可以承受这些负载压力,因此短链服务使用 302 状态码构造重定向响应

3. 高并发挑战方案

系统调用可以分成两种情况:

  1. 应用请求生成短URL的过程
  2. 用户访问短URL,通过短链跳转到长URL的过程

情况1:请求生成短URL不会太频繁,因为是商家生成的,并不由客户生成,因此第一点并发的情况较少以及使用量会比较低,生成URL的性能瓶颈取决于计数器
情况2:由于是直接触达客户,一个短链可能被成千上万的客户访问,上述部署模型中也提到,主要通过负载均衡与缓存解决,在此的缓存选择了本地内存缓存,减少与分布式缓存网络请求的链路耗时,用户访问短链的泳道图如下:
访问短链泳道图.png
具体流程:

  1. 用户点击短URL,请求短链服务
  2. 短链服务解密短链Key生成短链的自增Id
  3. 通过自增Id到缓存中匹配是否有对应的长URL
  4. 缓存匹配不到则根据主键Id查询数据库
  5. 数据库中如果查不到长URL,则返回HTTP 404响应
  6. 数据库中如果查到长URL,则更新缓存,再更新数据库的访问次数,然后重定向到长URL

4. API授权校验

授权校验主要做了三重校验:

  1. Body携带的时间戳timestamp必须在60秒内
  2. Body携带的应用Code(app_code)必须是数据库中已存在的
  3. Headers携带的Token必须有效

Token的加密:由时间戳 + 应用秘钥 取大写Md5,具体值为:

$"timestamp={timestampStr}&&app_secret={appSecretStr}".ToMd5().ToUpper()

具体的授权流程如下:
API授权验证流程.png
请添加图片描述

四、Web管理后台

  • 登录页

image.png

  • 短链列表页

在这里插入图片描述

  • 在线生成页

在这里插入图片描述

  • 授权应用页

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

请添加图片描述

五、项目源码

这是一个基于.NET开源的短链生成及监控系统,它包含了在线生成短链、短链跳转长链、支持短链访问次数以及Web监控页面,可以帮助我们更容易地生成短链、监控短链!

  • https://github.com/Bryan-Cyf/SuperShortLink
  • 欢迎大家提出PR,共同讨论进步

请添加图片描述

六、思考

  1. 用户每次请求生成短 URL 的时候,短链服务都会返回一个新生成的短 URL,也就意味着,如果用户重复提交同一个长 URL 请求生成短 URL,每次都会返回一个新的短 URL。你认为这将导致什么问题?
  2. 用户如果同时请求大量的无效短链过来,会遇到什么问题?

欢迎在评论区提出解决方法,没有思路的可私聊或者看源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/421779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python+requests+unittest+excel接口自动化测试框架

一、框架结构: 工程目录 二、Case文件设计 三、基础包 base 3.1 封装get/post请求(runmethon.py) 1 import requests2 import json3 class RunMethod:4 def post_main(self,url,data,headerNone):5 res None6 if heade…

互联网医院源码|搭建互联网医院系统时运营需要哪些资质?

目前一线城市已经都有完善的医疗系统,人们对于线上问诊系统越来越熟悉,使用的人也越来越多,对于一些偏远的地区来说在线问诊平台有着更广泛的应用和意义,互联网医院开发实现了医疗资源共享的情况,打破了地域限制&#…

文献管理软件Endnote、Mendeley、Zotero比较及选择,Zotero基础使用技巧

引言 大家好,我是比特桃。日常开发的项目分为两种,一种是成熟化的工程项目,只需要与具体的业务紧密结合及应用,难点也比较偏向于软件工程或者互联网高并发的方向。这种项目我们通常不会选择去查文献去寻找问题的解决办法&#xf…

微信小程序开发 | 音乐小程序项目

音乐小程序项目3.1 开发前的准备3.1.1 项目展示3.1.2 项目分析3.1.3 项目初始化3.2 【任务1】标签页切换3.2.1 任务分析3.2.2 前导知识3.2.3 编写页面结构和样式3.2.4 实现标签页切换3.3 【任务2】音乐推荐3.3.1 任务分析3.3.2 前导知识3.3.3 内容区域滚动3.3.4 轮播图3.3.5 功…

15-721 chapter2 内存数据库

Background 随着时代的发展,DRAM可以容纳足够的便宜,容量也变大了。对于数据库来说,数据完全可以fit in memory,但同时面向disk的数据库架构不能很好的发挥这个特性 这张图是disk database的cpu instruction cost 想buffer pool…

使用PyG(PyTorch Geometric)实现基于图卷积神经网络(GCN)的节点分类任务

文章目录基本介绍PyTorch Geometric图卷积神经网络GCN节点分类任务实现Cora数据集搭建GCN模型训练与测试迭代并输出完整代码基本介绍 PyTorch Geometric PyG(PyTorch Geometric)是一个基于PyTorch的库,可以轻松编写和训练图神经网络&#x…

ChatGPT,开启人机交互新篇章

ChatGPT在世界掀起了生成式AI的热潮,2个月实现月活用户过亿,是人类有史以来突破1亿人用户最快的消费端互联网产品,打破了Tiktok9个月破亿用户的纪录。不少专家将其视为第四次工业革命,资本市场也贡献大量涨停。当第一波的热情消退…

Android 7.1 Toast修复之终极篇,进程不奔溃(包含apk和兼容外来dex插件)

修复android 7.1 Toast的篇章: 常规app通过ams lancet 字节编码处理:Android Lancet Aop 字节编码修复7.1系统Toast问题(WindowManager$BadTokenException)多渠道游戏app兼容性处理:Android 7.1 Toast修复之多渠道包动态使用Booster或者Lancet plugin …

在外web浏览器远程访问jupyter notebook服务器【内网穿透】

文章目录前言视频教程1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口转载自远控源码文章:公网远程访问jupyter notebook【cpolar内网穿透】 前言 Jupyter Notebook,它是一个交…

未来城市的微小单元:滴滴即将量产无人车

汽车诞生之后就一直作为除了家庭与公司之外的「第三空间」存在,技术的脚步从未停止过开发汽车的更多可能。尤其无人驾驶技术的出现,进一步解放了驾驶者,也让人们对于这一能够自主移动的第三空间充满了想象。作为未来城市的微小组成单元&#…

( “树” 之 DFS) 226. 翻转二叉树 ——【Leetcode每日一题】

226. 翻转二叉树 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1] 示例 2: 输入:root [2,1,3] 输出:[…

ThreadLocal源码分析及内存泄漏

ThreadLocal原理分析及内存泄漏ThreadLocal的使用ThreadLocal原理set方法解析replaceStaleEntry方法解析expungeStaleEntry方法解析cleanSomeSlots方法解析case 1: 向前有脏数据,向后找到可覆盖的Entrycase 2: 向前有脏数据,向后未找到可覆盖的Entrycase…

吴恩达机器学习--线性回归

文章目录前言一、单变量线性回归1.导入必要的库2.读取数据3.绘制散点图4.划分数据5.定义模型函数6.定义损失函数7.求权重向量w7.1 梯度下降函数7.2 最小二乘法8.训练模型9.绘制预测曲线10.试试正则化11.绘制预测曲线12.试试sklearn库二、多变量线性回归1.导入库2.读取数据3.划分…

掌握高效绘制地图的利器——LeafletJs

文章目录前言一、leafletJs是什么?二、快速入门1、安装2、快速入门三、进阶学习1、Map 控件2、Marker 标记3、Popup 弹出窗口4、图层四、项目实战封装文件4.1 基础点位图4.2 行驶轨迹图前言 GIS 作为获取、存储、分析和管理地理空间数据的重要工具,用 G…

数据结构与算法一览(树、图、排序算法、搜索算法等)- Review

算法基础简介 - OI Wiki (oi-wiki.org) 文章目录1. 数据结构介绍1.1 什么是数据结构1.2 数据结构分类2. 链表、栈、队列:略3. 哈希表:略4. 树4.1 二叉树4.2 B 树与 B 树4.3 哈夫曼(霍夫曼)树:Huffman Tree4.4 线段树&a…

编辑文件/文件夹权限 - Win系统

前言 我们经常会遇到由于权限不够无法删除文件/文件夹的情况,解决方案一般是编辑文件/文件夹的权限,使当前账户拥有文件的完全控制权限,然后再进行删除,下文介绍操作步骤。 修改权限 查看用户权限 右键文件/文件夹,…

(函数指针) 指向函数的指针

函数指针- 指向函数的指针函数指针的声明和使用通过函数指针调用函数函数指针做参数函数指针数组函数指针的声明和使用 函数指针的声明格式: 返回值类型 (*函数指针名)(参数列表); 其中: *函数指针名 表示函数指针的名称返回值类型 则表示该指针所指向…

【Kubernetes】StatefulSet对象详解

文章目录简介1. StatefulSet对象的概述、作用及优点1.1 对比Deployment对象和StatefulSet对象1.2 以下是比较Deployment对象和StatefulSet对象的优缺点:2. StatefulSet对象的基础知识2.1 StatefulSet对象的定义2.1.1 下表为StatefulSet对象的定义及其属性&#xff1…

上岸川大网安院

一些感慨 一年多没写过啥玩意了,因为考研去了嘿嘿。拟录取名单已出,经历一年多的考研之路也可以顺利打上句号了。 我的初试成绩是380,政治65,英语81,数学119,专业课115。 回顾这一路,考研似乎也…

分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测

分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测 目录分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测分类效果基本介绍模型描述程序设计参考资料分类效果 基本介绍 MATLAB实现CNN-BiLSTM-Attention多输入分类预测,CNN-BiLSTM结合注意力机制多输…