Java生成短网址|短链接

Java生成短链接 (文章)
https://www.cnblogs.com/xijin-wu/p/8483649.html
https://www.seoxiehui.cn/article-156919-1.html
https://search.gitee.com/?skin=rec&type=repository&q=%E7%9F%AD%E7%BD%91%E5%9D%80&repo=&reponame=&lang=java

Java netcore
1. Wei.TinyUrl
https://github.com/a34546/Wei.TinyUrl

1.1shorturl
https://github.com/wjup/shorturl

2. ShortURL
https://github.com/zhaopeiym/ShortURL

3.基于JavaFx搭建的实用小工具集合
https://github.com/864381832/xJavaFxTool

4.Alkaids/shortcut   ***
https://github.com/Alkaids/shortcut

 ******************************************************************************************************************************************

1.Twitter的分布式雪花算法 SnowFlake 每秒自增生成26个万个可排序的ID (Java版)
https://blog.csdn.net/yanpenglei/article/details/79542768

2.Twitter的雪花算法(snowflake)自增ID
https://www.cnblogs.com/jifeng/p/9802142.html

*******************************************************************************************************************************************

__________________________________________________________________________________________________

在知乎看到这篇贴子谈论短地址生成的方法。 主要步骤为两个:

实现一个不会重复的发号器
每个新的请求都给它一个新的号码,转换成62进制,62进制是带有阿拉伯数字,英文大小写的格式,比较适合作为短地址的 url.

发号器

直接不造轮子了,用 Twitter 的雪花算法。

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 

1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
41位时间截(毫秒级) 一般来说这个时间能够使用69年.
10位的数据机器位,可以部署在1024个节点
12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
加起来刚好64位,为一个Long型。

进制转换

通过上述发号器得到的Long类型的数据,转换为62进制,比如

6628238651141500928

转换为

7TDp0rS917i

下面这个字符串就是需要的短地址。

重定向

通过 curl -i http://127.0.0.1:9527/7TDhjcamrAI 应用会匹配末端的字符串,去redis里面拿到url,然后通过状态码 302 重定向即可。

二维码生成

使用 Google 的 zxing 做的二维码转换,详细代码可参考这里

性能测试

使用 JMH 做性能基准测试,环境为 CPU: 2.2 GHz Intel Core i7; Memory: 16 GB; OS: Mac OSX

 Options options = new OptionsBuilder().include(BenchmarkTest.class.getName()+".*")
                .warmupIterations(1) // 预热
                .warmupTime(TimeValue.seconds(1))
                .measurementIterations(5)// 一共测试10轮
                .measurementTime(TimeValue.seconds(5))// 每轮测试的时长
                .forks(1)// 创建几个进程来测试
                .threads(16)// 线程数
                .build();

测试结果如下:

Benchmark                      Mode  Cnt    Score    Error  Units
BenchmarkTest.httprequest     thrpt    5  1948.349 ± 2028.032  ops/s
BenchmarkTest.serviceRequest  thrpt    5  3945.100 ± 1185.980  ops/s

httprequest 是通过 okhttp 构造 post 请求,直接请求本地前端控制方法。qps 大概 2000 左右。
serviceRequest 是直接调用本地方法服务得到短地址,qps 大概是 http 测试的两倍,有 4000 左右,比较理想。

进一步的优化空间可以关注一下进制转换部分,有不必要的基本类型转换。

____________________________________________________________________________________________________________________________

原理:

Ø  通过发号策略,给每一个请求的长地址分配一个唯一编号,小型系统直接利用数据库的自增主键就可以。

Ø  如果大型应用,可以考虑实现分布式发号器,不断自增就行。第一个使用这个服务的人得到的短地址是http://www.shururl.com/0 第二个是 http:// www.shururl.com /1 第10个是 http://www.shururl.com /a 第依次往后.

实现处理流程:

 

A.   核心步骤:

实现唯一发号器.
每个请求获取一个唯一编号,转换成62进制,62进制是由 英文字母(大小写)、阿拉伯数字等格式组合,作为短地址的短码.

B.        发号器规则:

计算的来源思路: Twitter 雪花算法

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 

1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0.
41位时间截(毫秒级) 这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;
5位的数据中心,可以存在在32个数据中心
5位的机器位,每1个数据中心可以部署32个节点

12位序列号,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号
加起来刚好64位,为一个Long型。

C.        进制转换:

通过上述发号器得到的Long类型的数据,转换为62进制,比如:6628238651141500928  转换为: 7TDp0rS917i 下面这个字符串就是需要的短地址,http://127.0.0.1/7TDp0rS917i

 

 

 

 

详细思路: 

1.      根据发号器的数量,在mongo中建立一张表

 

发号器Id

发号器名称

机器标识

数据中心标识[LP3] 

应用描述信息

XXX

1号发号器

1

1

Desc.

XXX

2号发号器

2

1

Desc.

XXX

3号发号器

3

1

Desc

XXX

1号发号器

1

2

Desc

XXX

2号发号器

2

2

Desc

指定数据中心的发号器的个数,及配置信息相关.

 

2.      根据上面[实现处理流程-B的处理思路:

1符号位+41位时间截+5位的数据中心位+5位的机器位+12位序列号=64位,一个Long型.

 

3.  将2步计算获取的10进制数字转换为62用如:数字10000给它的短地址对应的编号是9999,我们将通过雪花算法获取的9999,做一个10进制到62进制的转换。

4.      解决发号器的大并发高可用问题,就是将发号器做成分布式,那么多节点要保持同步加1,根据CAP的理论,多点同时写入保证一致性(Consistency),是不可能真正做到的。解决办法: 可以实现多个发号器,根据上面的原则我们可以实现32个逻辑发号器,分别发尾号为0到31的号。每发一个号,在5位机器号的基础上,不断加1,这些发号器互相独立,互不干扰。

5.      跳转用301还是302。301是永久重定向,302是临时重定向。短地址一经生成就不会变化,所以用301是符合http语义的。同时对服务器压力也会有一定减少。但是如果使用了301,我们就无法统计到短地址被点击的次数了。而这些信息的捕捉,是数据分析的重要来源。虽然302会增加服务器压力,但却是一个最好的选择。


Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注