📣读完这篇文章里你能收获到
短 URL 生成器,也称作短链接生成器,就是将一个比较长的 URL 生成一个比较短的URL,当浏览器通过短 URL 生成器访问这个短 URL 的时候,重定向访问到原始的长 URL目标服务器,访问时序图如下:
用户访问短URL时序描述:
短链管理,短链系统管理员可以在管理后台做以下操作:
秘钥使用时序图如下:
秘钥使用流程描述:
概要设计阶段主要关注短链服务的用例、部署模型、领域设计及短链生成方案的选择
短链服务的业务逻辑比较简单,相对比较有挑战的就是高并发的短URL的访问请求如何处理。高并发访问主要通过负载均衡与缓存解决。具体的架构图如下:
领域设计这块分为两部分,一部分是短链生成记录,另一部分是应用授权
短 URL 生成器的设计核心就是短 URL 的生成,即长 URL 通过某种函数,计算得到n个字符的短 URL。短 URL 有几种不同的生成算法。由于Base64后面两位的“+”和“/”在 URL 中会被编码为“%2B”以及“%2F”,需要进行再编码,因此不考虑后两位符号,下文皆以Base62编码([A-Z],[a-z],[0-9])作为描述
散列函数可以将任意长度的输入(又叫做预映射, pre-image),通过执行复杂的运算,变成固定长度的输出又叫散列值, hash value)。在短URL生成中,散列函数可用于将长URL映射到短URL,从而达到缩短URL的效果。
通常的设计方案:
具体流程如图:
这样的冲突处理需要多次到存储中查找 URL,无法保证短链服务的性能要求,不考虑该方案
预生成短URL是指提前生成一些短URL并保存到数据库中,当用户需要缩短长URL时,直接从数据库中获取一个未被使用过的短URL,而不是现场生成新的短URL。
通常的设计方案:
具体流程如图:
由于需要提前占用大量的存储空间,所以暂不考虑该方案
自增短 URL 一种免冲突的算法是用自增长自然数来实现,即维持一个自增长的二进制自然数,然后将该自然数进行 Base62 编码即可得到一系列的短 URL。这样生成的的短 URL 必然唯一,通常采用自增序列号的方式进行生成。原理是将每一个长链接映射到一个唯一的自增序列号,然后将自增序列号转换为指定长度的短链接
比如:
弊端:但是这种算法将导致短URL是可猜测的,只要知道了其中一个短 URL,就可以猜测下一个短 URL
为了解决上述问题,基于上面的方式在生成时加入随机打乱编码Base62等混淆方法,可以增加被预测的概率,增强短URL的安全性
通常的设计方案:
具体流程如图:
我们就是采用了基于混淆的自增短URL,计数器避免引入过多的中间件,因此选择了数据库自增主键
在详细设计阶段,主要考虑重定向码、高并发场景应对方案、混淆加解密算法的解析及API授权校验的流程
其中“+”和“/”在 URL 中会被编码为“%2B”以及“%2F”,需要进行再编码,因此直接使用标准 Base64 编码进行短URL 编码并不合适,所以,我们需要针对 URL 场景对 Base64 编码进行改造,Base64 编码表中的 62,63 进行编码移除,更新为Base62编码
举例:打乱成:s9LFkgy5RovixI1aOf8UhdY3r4DMplQZJXPqebE0WSjBn7wVzmN2Gc6THCAKhaut
计数器自增Id | 标准Base62编码 | 标准Base62编码(6位字符) | 打乱后Base62编码 | 打乱Base62编码(6位字符) |
---|---|---|---|---|
6 | G | AAAAAG | y | sssssy |
66 | BE | AAAABE | 9k | ssss9k |
100 | Bm | AAAABm | 9E | ssss9E |
可以看出,虽然打乱了,但还顺序性还是很明显
计数器自增Id | 打乱后Base62编码(6位字符) | 前面补0到10位 | 倒转数字 | 倒转后的打乱Base62编码(6位字符) |
---|---|---|---|---|
6 | sssssy | 0000000006 | 6000000000 | yPFrgP |
66 | ssss9k | 0000000066 | 6600000000 | 5xWCQH |
100 | ssss9E | 0000000100 | 10000000 | ssSKph |
将请求收到的短链Key根据打乱后的Base62编码转成十进制数,补0到10位,然后倒转就得到原来的短链Id
短链Key | 解析后的十进制数 | 前面补0到10位 | 倒转数字 |
---|---|---|---|
yPFrgP | 6000000000 | 6000000000 | 6 |
5xWCQH | 6600000000 | 6600000000 | 66 |
ssSKph | 10000000 | 0010000000 | 100 |
短链长度 | 最大支持数 | 数据量级 |
---|---|---|
5 | 99999999 | 亿 |
6 | 9999999999 | 百亿 |
7 | 999999999999 | 万亿 |
满足短 URL 重定向要求的 HTTP 重定向响应码有 301 和 302 两种
一般来说,使用 301 状态码可以降低短链服务器的负载压力,但无法统计短 URL 的使用情况,而短链服务的架构设计完全可以承受这些负载压力,因此短链服务使用 302 状态码构造重定向响应
系统调用可以分成两种情况:
情况1:请求生成短URL不会太频繁,因为是手动点击生成的,因此第一点并发量会比较低,生成URL的性能瓶颈取决于计数器
情况2:由于是直接触达客户,一个短链可能被成千上万的客户访问,上述部署模型中也提到,主要通过负载均衡与缓存解决,在此的缓存选择了本地内存缓存,减少与分布式缓存网络请求的链路耗时,用户访问短链的泳道图如下:
具体流程:
授权校验主要做了三重校验:
Token的加密:由时间戳 + 应用秘钥 取大写Md5,具体值为:
$"timestamp={timestampStr}&&app_secret={appSecretStr}".ToMd5().ToUpper()
具体的授权流程如下:
这是一个基于.NET开源的短链生成及监控系统,它包含了在线生成短链、短链跳转长链、支持短链访问次数以及Web监控页面,可以帮助我们更容易地生成短链、监控短链!
欢迎在评论区提出解决方法,没有思路的可私聊或者看源码