zoukankan      html  css  js  c++  java
  • 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
    
    1. httprequest 是通过 okhttp 构造 post 请求,直接请求本地前端控制方法。qps 大概 2000 左右。
    2. 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会增加服务器压力,但却是一个最好的选择。


  • 相关阅读:
    WEB安全 php+mysql5注入防御(一)
    Spring 整合 Quartz 实现动态定时任务(附demo)
    dubbo工作原理(3)
    dubbo服务降级(2)
    dubbo服务降级(1)
    程序员决对不能缺少产品思维
    GNUPG
    idea远程debug:tomcat
    基于JavaMail的Java邮件发送:复杂邮件发送
    使用javaMail发送简单邮件
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/13026529.html
Copyright © 2011-2022 走看看