什么是短链接服务
短链接服务将原本较长的网址转化成较短的网址,从而便于用户的记忆与社交软件上的传播。 假设,我们要做一次简单的营销活动,活动流程大体如下:
首先,将营销落地页,一个较长的 URL ( https://www.glo.com/2021/09/15/ddd/tactics/introduction/#more ) 通过短链接服务转化为一个比较短的 URL( http://glo.com/s );然后,通过营销渠道将短链接发送给目标用户(比如短信);在用户获得短链接后,通过链接访问短链接服务。系统接受请求并将请求重定向到原始的长链地址;最后,用户使用长链地址直接访问目标网站,从而获得最终响应结果。
整体流程如下:
enter image description here
短链接服务的核心流程主要包括 创建短链接 和 访问短链接 。 系统设计要点
短链接服务的核心流程主要围绕 Key 和 Map 进行构建的,如:
创建短链接。首先,生成一个 Key,将长链地址作为 value 保存到 Map 中,然后将短链域名和 key 拼接成短链接,返回给调用方;访问短链接。服务从 URL 中提取 key,然后在 Map 中查找目标链接,对目标地址做重定向处理。
Map 结构我们可以基于 MySQL 和 Cache 进行构建,那就剩下如下问题了:
Key 怎么来,又是怎么维护的?如何通过 Http 协议进行请求重定向?
2.1 Key 生成
通常情况下,Key 的生成方式由很多。但对于短链接服务来说,生成 Key 的长度是一个非常重要的指标。 首先,生成的 Key 不能重复;其次,Key 要尽可能短。 这样才能使最终短链长度尽可能的小。
基于此,我们无法使用分布式 Key 生成算法,如 UUID。最佳的生成策略应该是基于 Number 自增的方案。结论: 我们需要一个基于 Number 自增的 Key 生成器。 2.2 Key 编解码
如果我们使用 Number 作为 Key,那么还有没有方案进一步压缩 Number 长度呢? 对于数字来说:
8 进制比 2 进制短;10 进制比 8 进制短;16 进制比 10 进制短;......
因此,我们可以使用高进制对数字 Key 进行编解码,从而进一步压缩 Key 的长度。 2.3 请求重定向
请求重定向是 HTTP 协议的一部分,JEE 的 HttpServletResponse 就提供重定向接口,同时 Spring MVC 对其也提供了支持。 基于 HttpServletResponse 的重定向:
public void redirect(@PathVariable String code, HttpServletResponse response) throws IOException { String url = getTargetUrl(code); // 调用 sendRedirect 方法,进行请求重定向 response.sendRedirect(url);}
基于 Spring MVC 的重定向:
public ModelAndView redirect(@PathVariable String code){ String url = getTargetUrl(code); // 使用 RedirectView,进行请求重定向 RedirectView redirectView = new RedirectView(); redirectView.setUrl(url); return new ModelAndView(redirectView);}
要点分析完成后,让我们先把 maven 项目搭建起来。
项目搭建
该项目使用 Spring Boot 作为主要开发框架。 项目依赖组件:
组件 | 含义 | spring-boot-starter-web | Web | flyway | 数据库管理 | Junit | 测试 | lombok | 自动生成getter、setter | 3.1. 项目生成
浏览器中输入 https://start.spring.io/ ,打开 spring-boot 项目生成器,按照下列配置生成项目:
名称 | 值 | 项目类型 | maven | 语言 | java | Boot版本 | 2.1.1 | group | com.geekhalo | artifact | tinyurl | dependency | web、flyway、lombok |
点击“Generate Project”,生成并下载项目。 将下载的项目解压,得到一个完整的 maven 项目,打开熟悉的 IDE,将项目导入到 IDE 中。我们生成了一个空的 Spring Boot 项目,稍后的所有操作都会基于这个项目完成。 项目成功生成后,让我们对系统进行进一步分析。首先,需要对系统中的核心组件进行梳理。
核心组件
4.1 NumberGenerator
其接口签名如下:
public interface NumberGenerator { /** * 生成自增 Key * @return */ Long nextNumber(NumberType type);}4.2 NumberEncoder
对 Number 进行编解码操作,以进一步减少 Key 的长度。 其接口签名如下:
public interface NumberEncoder { /** * 对 Number 进行编码 * @param id * @return */ String encode(Long id); /** * 对 Number 进行解密 * @param str * @return */ Long decode(String str);}4.3 TargetUrlRepository
其接口定义如下:
public interface TargetUrlRepository { /** * 添加链接 * @param targetUrl */ void save(TargetUrl targetUrl); /** * 获取连接 * @param id * @return */ TargetUrl getById(Long id);}
至此,系统核心组件就分析完了。接下来,让我们看下核心流程。
核心流程
5.1 创建短链接
创建短链接,主要服务于内部系统,将较长的 URL 地址提交到短链接服务,并获取与之对应的较短的 URL 地址。 创建短链接流程大体如下:
enter image description here
详细流程如下: |