我(wǒ)是(shì)@程序员小助手, 本文从技术角度,对短(duǎn)网址(zhǐ)进行深度挖掘。
前言(yán)网上已经有产品,用(yòng)着还不錯(cuò)。可(kě)是(shì),作为程序员,从零(líng)开始造轮子,开发一(yī)個(gè)属于自己的(de)短(duǎn)网址(zhǐ)服務(wù)器,這(zhè)想法amazing!
通过本文,读者可(kě)明白短(duǎn)网址(zhǐ)的(de)技术原(yuán)理,以及通过Go语言(yán)实现一(yī)個(gè)短(duǎn)网址(zhǐ)服務(wù)。
简明教程短(duǎn)网址(zhǐ)为什么存在?
微(wēi)博等(děng)产品的(de)兴起,活跃了(le)网上的(de)社交圈(quān)内大多数用(yòng)户。但是(shì)微(wēi)博一(yī)般有140字限制(zhì),如果不转发,单纯评论文字,再加上一(yī)段网址(zhǐ),极有可(kě)能超过限制(zhì)而被截断。
短(duǎn)网址(zhǐ)应运而生,用(yòng)较短(duǎn)的(de)一(yī)個(gè)字符(fú)串(chuàn),替换较长的(de)一(yī)個(gè)字符(fú)串(chuàn),从观感上讲,效果要友好的(de)多。
从技术原(yuán)理上说,短(duǎn)网址(zhǐ)是(shì)一(yī)個(gè)hash表(biǎo),用(yòng)于映射两個(gè)字符(fú)串(chuàn)的(de)对应关系。
使(shǐ)用(yòng)鍵(jiàn),找到对应的(de)值,重定向进行访问,就完成(chéng)了(le)整個(gè)流程。
短(duǎn)网址(zhǐ)算(suàn)法短(duǎn)网址(zhǐ)的(de)一(yī)般结构,比如新浪的(de) SwuTjn,其中后端的(de)一(yī)段6位字符(fú)串(chuàn),就是(shì)用(yòng)来唯一(yī)標(biāo)记一(yī)條(tiáo)记錄(lù)的(de)ID。那么,使(shǐ)用(yòng)什么算(suàn)法,可(kě)以生成(chéng)一(yī)條(tiáo)无重复的(de)ID呢?
使(shǐ)用(yòng)通用(yòng)的(de)做法,使(shǐ)用(yòng) 0-9 A-Z a-z 一(yī)共62個(gè)字符(fú),我(wǒ)們(men)看使(shǐ)用(yòng)hash鍵(jiàn)位数分别有多少种排列组合情(qíng)况。
1位:pow(62,1) = 62 种
2位:pow(62,2) = 3844 种
3位:pow(62,3) = 238328 种
4位:pow(62,4) = 14776336 种
5位:pow(62,5) = 916132832 种
6位:pow(62,6) = 56800235584 种
一(yī)般情(qíng)况下,6個(gè)字符(fú),就足够使(shǐ)用(yòng)了(le),共计568亿种可(kě)能。
还有一(yī)种情(qíng)况是(shì),用(yòng)原(yuán)网址(zhǐ)字符(fú)串(chuàn)的(de)MD5值,共计32位,然后通过切分为4段,分别按位与运算(suàn),并裁剪到30位。間(jiān)隔5位选出(chū)该位的(de)字符(fú)作为该段索引,共有6位。但是(shì)這(zhè)种做法也有几率发生重复,也不直观。
因此本文使(shǐ)用(yòng)第一(yī)种算(suàn)法生成(chéng)鍵(jiàn)ID。
工具(jù)準(zhǔn)备分析短(duǎn)网址(zhǐ)的(de)特(tè)性,包含以下项目:
唯一(yī)性:鍵(jiàn)需要全局唯一(yī)时效性:鍵(jiàn)需要有过期时間(jiān)目標(biāo)网址(zhǐ)唯一(yī),如果重复,则自动返回既有的(de)鍵(jiàn)。考虑到上述情(qíng)形,我(wǒ)們(men)使(shǐ)用(yòng)redis存储這(zhè)些对应关系。使(shǐ)用(yòng)Gin框架作为路由和控制(zhì)器,提(tí)供对外的(de)API访问。
核心函(hán)数计算(suàn)机中常见的(de)2进制(zhì),8进制(zhì),10进制(zhì),16进制(zhì),我(wǒ)們(men)此处需要使(shǐ)用(yòng)62個(gè)字符(fú),循环表(biǎo)示一(yī)個(gè)整数,那么可(kě)称之为62进制(zhì)。
下面使(shǐ)用(yòng)go语言(yán)实现這(zhè)個(gè)函(hán)数,用(yòng)于将任意的(de)整数(uint64)转换为(0-9A-Za-z)的(de)字符(fú)串(chuàn)。
需要注意,基础的(de)方法,就是(shì)循环取余数,根据进制(zhì)字典,索引相应的(de)字符(fú),然后将各個(gè)余数拼接(jiē)出(chū)来,就是(shì)结果。
這(zhè)個(gè)计算(suàn)方法,与2进制(zhì),8进制(zhì),原(yuán)理是(shì)相同的(de)。
由于字典比较长,有62個(gè)鍵(jiàn)值对,我(wǒ)們(men)仅列出(chū)一(yī)部分。
上述函(hán)数的(de)转换结果,类似于 6489264001 = 75ai0p
功能规划下面是(shì)对于系统路由,创建短(duǎn)鏈(liàn)接(jiē),以及使(shǐ)用(yòng)短(duǎn)鏈(liàn)接(jiē)访问目標(biāo)网址(zhǐ)的(de)方法。
1 - 规划路由
路由比较简单,一(yī)共2個(gè),一(yī)個(gè)POST方法,生成(chéng)短(duǎn)鏈(liàn)接(jiē);一(yī)個(gè)是(shì)GET方法,访问短(duǎn)鏈(liàn)接(jiē)。
代(dài)码如下:
2 - 引入redis并初(chū)始化
为了(le)方便演示,我(wǒ)們(men)使(shǐ)用(yòng)redis存储鍵(jiàn)值,并設(shè)置expire时間(jiān)。
"github.com/gin-gonic/gin" "github.com/go-redis/redis/v7"我(wǒ)們(men)使(shǐ)用(yòng)go-redis提(tí)供的(de)接(jiē)口操作redis数据库。
下面是(shì)全局的(de) redis.Client
对象生成(chéng),和初(chū)始化函(hán)数。
這(zhè)样做的(de)好处是(shì),我(wǒ)們(men)全局都可(kě)以使(shǐ)用(yòng)变量 rdb 调用(yòng)方法操作redis鍵(jiàn)值。
3 - 实现POST路由方法:add
本函(hán)数用(yòng)于接(jiē)收form表(biǎo)单数据,生成(chéng)一(yī)個(gè)全局唯一(yī)的(de) hash ,作为鍵(jiàn),存入redis,設(shè)置值和过期时間(jiān)。
代(dài)码如下:
本段我(wǒ)們(men)使(shǐ)用(yòng)了(le)一(yī)個(gè) getCounter 函(hán)数,這(zhè)是(shì)設(shè)置在redis内的(de)鍵(jiàn),将其每次请求创建的(de)时候,自增+1,可(kě)保证无重复。根据這(zhè)個(gè)计数器,我(wǒ)們(men)调用(yòng) helper的(de) DecToAny 方法,将其转化为62进制(zhì)的(de)字符(fú)串(chuàn),作为全局唯一(yī)的(de) hash 值。
下图是(shì) getCounter 的(de)定义:
特(tè)别注意的(de)是(shì),helper包,就是(shì)我(wǒ)們(men)在“核心函(hán)数”部分定义的(de)函(hán)数。在主函(hán)数体内引用(yòng)。
4 - 实现GET方法:visit
本函(hán)数主要用(yòng)于使(shǐ)用(yòng)上一(yī)节接(jiē)口生成(chéng)的(de)短(duǎn)鏈(liàn)接(jiē),进行访问,并自动重定向到目標(biāo)网址(zhǐ)。
代(dài)码如下:
对于不存在的(de)短(duǎn)鏈(liàn)接(jiē),或者redis获取失败,返回錯(cuò)误信息(xī)。
如果存在,使(shǐ)用(yòng) 301 = StatusMovedPermanently 状态码重定向到目標(biāo)地址(zhǐ)。
测試(shì)我(wǒ)們(men)使(shǐ)用(yòng)curl工具(jù),测試(shì)上述两個(gè)接(jiē)口。
首先,使(shǐ)用(yòng)POST表(biǎo)单提(tí)交数据:
curl -s -X POST -d "target=/
上述方法,我(wǒ)們(men)提(tí)交了(le)两個(gè)参数,命中路由之后,会访问上一(yī)节第3條(tiáo)的(de)add方法,并生成(chéng)一(yī)個(gè)短(duǎn)鏈(liàn)接(jiē)网址(zhǐ)。返回JSON格式数据如下:
{"message":"ok","short_url":"}
其中,short_url 就是(shì)短(duǎn)网址(zhǐ)。
接(jiē)着,我(wǒ)們(men)在使(shǐ)用(yòng)curl访问這(zhè)個(gè)鏈(liàn)接(jiē),看是(shì)否发生重定向。截图如下:
可(kě)以看到,执行了(le)301重定向,并给出(chū)了(le)目標(biāo)网址(zhǐ),与我(wǒ)們(men)上述表(biǎo)单想要创建的(de)地址(zhǐ)一(yī)致。
最后,故障测試(shì)。访问一(yī)個(gè)不存在的(de)hash,看是(shì)否排除异常信息(xī)。截图如下:
可(kě)以看到,执行了(le)錯(cuò)误返回信息(xī)。
结语以上我(wǒ)們(men)使(shǐ)用(yòng)GO语言(yán)框架Gin实现了(le)两個(gè)路由,并使(shǐ)用(yòng)redis管理短(duǎn)鏈(liàn)接(jiē)。核心函(hán)数使(shǐ)用(yòng)helper包管理,经过测試(shì),实现了(le)短(duǎn)网址(zhǐ)的(de)功能。
以上代(dài)码在本地测試(shì)通过,也可(kě)部署到线上服務(wù)器对外开发端口,提(tí)供服務(wù),效果是(shì)一(yī)样的(de)。
希望通过這(zhè)個(gè)流程,使(shǐ)大家对于短(duǎn)网址(zhǐ)的(de)知识,有一(yī)些了(le)解(jiě),并能根据自身的(de)编程能力,创作出(chū)更好用(yòng)的(de)短(duǎn)网址(zhǐ)服務(wù)。
Happy coding :-)
【本文由 @程序员小助手 发布,持续分享编程与程序员成(chéng)长相关的(de)内容,欢迎关注】
网站开发的选择很多。 java和php开发首先,java和php都不能实现网站的全栈开发。 1、java给人一种重的感觉,优势是框架、组件、中间件丰富,除了web,还有云计算、大数据、人工智能的框架,...
这个问题的答案,就和问取个老婆多少钱一样,没有标准答案。取个老婆,得看你娶的是二婚的,还是头婚的?漂亮的还是一般的?贤惠的还是贪婪的?要不要求你买房买车?摆酒去五星级酒店还是家里自己做?做个网站也类似...
这个肯定是骗子!人口普查表只登记,绝没有拍照,更没有什么手持身份证。 我家也来了俩,直接让我给轰走了,什么证件都没有。后来去物业登记的。物业更简单,身份证等不用看,你只说自己信息,她登记就完事了。...
首先可以明确的告诉大家,即使我们将自己的域名解析至京东的节点IP或域名上,依旧是无法成功访问的,为什么呢? 域名与站点之间须双向绑定我们访问一个网站一般都是在浏览器中输入域名后回车就行了,看上去我们是...
你好,我是【你还是太阳的阳光】,很高兴为你解答。 需不需要这个自己决定即可,没有固定的规则。 手机并不是需要单独的域名才可以做网站的。 域名只是一个识别标志性的后缀,并不追求使用客户端 一个网站的域...
今天给各位分享胶南做网站的知识,其中也会对胶南信息港征婚交友进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!文章目录列表: 1、胶南做网站最低最便宜多少钱? 胶南做网站最低最便...
芙蓉镇位于花都市北部,距城区8公里,距广州市30公里,总面积46.5平方公里。全镇11900多人,下辖六个行政村,一个居委会,有3000多名本镇籍海外华侨。芙蓉镇地理环境优越,山青水秀,气候宜人,广东...
1、 传统建站一般先双方沟通,可以在线沟通,如:Q或者电话咨询一下,要对公司有个大概了解,比如:你网站的定位给谁看,展示什么,有什么大概要求……给出相关参考案例及报价,确定后签署协议,付款,出网站初稿...