Maison > Article > interface Web > Explication détaillée du service de liens courts implémenté par Nodejs+Nest
Cet article vous présentera la méthode de mise en œuvre d'un service de liens courts basé sur le framework Node Nest. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.
Étude recommandée : "tutoriel nodejs"
Nous pouvons voir toutes sortes de liens courts étranges dans la vie quotidienne. Chaque fois que je clique pour sauter, je me sens magique. Comment ce court lien guide-t-il les utilisateurs vers la bonne page ?
Le principe de la chaîne courte est de rendre un blog court plus long, alors comment transformer cette chaîne courte en une chaîne longue de liens ? S'appuie-t-il sur un algorithme de cryptage magique ? Non, il suffit de s'appuyer sur la relation de mappage clé/valeur pour réaliser facilement ce blog court et long apparemment magique.
Avec une image, tout le monde peut voir clairement l'ensemble du processus d'accès au lien court.
Tout d'abord, nous aurons un lien long. Grâce au traitement du service de liens courts, une URL avec une seule couche de répertoires sera généralement générée. la distribution d'URL obtenue.
Ensuite, il s'agit du côté utilisateur. Une fois que l'utilisateur clique sur le lien court, la première chose qu'il atteint n'est pas la page cible, mais le service de lien court.
Le service de lien court interceptera le chemin d'accès sur le lien et l'utilisera comme clé pour trouver la valeur correspondante dans la relation de mappage.
Si la valeur correspondante est introuvable, cela signifie que le lien court n'existe pas ou a expiré ; si la requête réussit, le service de lien court fera directement 302 vers le lien cible dans la valeur pour compléter un accès par lien court.
Matériaux : Fast-NestÉchafaudage, Redis
L'ensemble de la mise en œuvre est divisé en 3 parties :
@Post('/createUrl') async createUrl( @Body('url') url: string, @Body('type') type: string, ) { const shortUrl = await this.shorturlService.createUrl(url, type); return { shortUrl, }; }
Créez une interface createUrl
dans le service, recevez les champs url
et type
, et transmettez-les dans shorturlService
, en attendant le lien court à générer Puis sortie.
async createUrl(url: string, type: string = 'normal') { const urlKey = await this.handleUrlKey(); const dataStr = JSON.stringify({ url, type }); await this.client.set(urlKey, dataStr, type === 'permanent' ? -1 : 300); return `${Config.defaultHost}/${urlKey}`; } private async handleUrlKey(count?: number): Promise<string> { const _count = count || 1; const maxCount = Config.maxRetryTimes; if (_count >= maxCount) throw new HttpException('超过重试次数,请重新生成链接', HttpStatus.INTERNAL_SERVER_ERROR); const urlKey: string = Math.random().toString(36).slice(-4); const _url = await this.client.get(urlKey); if (_url) { return await this.handleUrlKey(_count + 1); } return urlKey; }
Obtenez d'abord une chaîne aléatoire à 4 chiffres via Math.random().toString(36).slice(-4)
, qui sera utilisée comme nom de chemin de la chaîne courte.
Avant de cartographier, nous devons juger de son caractère unique, même si cela est peu probable, nous devons néanmoins éviter des problèmes tels que la couverture en chaîne courte. La solution de ce service est de réessayer de générer. Si la valeur de la chaîne courte est malheureusement répétée, elle entrera dans la branche de nouvelle tentative. Le service aura un nombre de tentatives intégré. Si le nombre de tentatives dépasse le nombre de mots configuré. cette conversion renverra un échec.
En plus de url
, la méthode createUrl
accepte également un champ type
, qui implique les caractéristiques de liens courts spéciaux. Nos liens courts ont trois modes :
Après avoir généré urlKey
, il sera converti avec type
La chaîne est stockée dans Redis et le lien court épissé est généré.
@Get('/:key') @Redirect(Config.defaultIndex, 302) async getUrl( @Param('key') key: string, ) { if (key) { const url = await this.shorturlService.getUrl(key); return { url } } } // this.shorturlService.getUrl async getUrl(k: string) { const dataStr = await this.client.get(k); if (!dataStr) return; const { url, type } = JSON.parse(dataStr); if (type === 'once') { await this.client.del(k); } return url; }
Le côté utilisateur obtiendra un lien similaire à http://localhost:8000/s/ku6a
Cliquer dessus équivaut à envoyer une requête GET au service de lien court. .
Après avoir reçu la demande, le service obtient la valeur du champ clé dans le lien, qui est la chaîne ku6a
, et l'utilise pour trouver la relation de mappage dans Redis.
Il y a deux branches ici. La première est que la valeur pertinente ne peut pas être interrogée dans Redis. Le service pense que le lien court a expiré et reviendra directement car getUrl
renvoie une valeur nulle, le décorateur de redirection. will Cette requête est redirigée vers le lien cible par défaut.
Si la valeur pertinente est trouvée avec succès dans Redis, les champs url
et type
seront lus. Si le type est une fois, cela signifie qu'il s'agit d'un lien unique et la méthode de suppression sera. activement déclenché. Le lien cible sera finalement renvoyé.
Lors de l'utilisation de liens courts, il est fort probable que des statistiques de données pertinentes soient nécessaires. Comment collecter des données sans. en utilisant une base de données ? Qu'en est-il des statistiques ?
Dans ce service, nous pouvons compléter le rapport d'accès aux liens courts le même jour en scannant le fichier journal d'atterrissage.
Lors de la génération de liens courts, ajoutez le champ urlID pour la différenciation statistique et générez activement les journaux, comme suit :
async createUrl(url: string, type: string = 'normal') { const urlKey = await this.handleUrlKey(); const urlID = UUID.genV4().toString(); const dataStr = JSON.stringify({ urlID, url, type }); this.myLogger.log(`createUrl**${urlID}`, 'createUrl', false); await this.client.set(urlKey, dataStr, type === 'permanent' ? -1 : 300); return `${Config.defaultHost}/${urlKey}`; }
然后在用户点击短链接时获取该短链接的urlID字段,并主动输出日志,如下:
async getUrl(k: string) { const dataStr = await this.client.get(k); if (!dataStr) return; const { url, type, urlID } = JSON.parse(dataStr); if (type === 'once') { await this.client.del(k); } this.myLogger.log(`getUrl**${urlID}`, 'getUrl', false); return url; }
这么一来我们将能够在服务的logs目录中获得类似这样的日志:
2021-04-25 22:31:03.306 INFO [11999] [-] createUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:38.323 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:39.399 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:40.281 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:40.997 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:41.977 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:42.870 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:43.716 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf 2021-04-25 22:31:44.614 INFO [11999] [-] getUrl**3f577625-474a-4e30-9933-e469ce3b0dcf
之后我们只需要以createUrl
的日志为索引,对getUrl
类型的日志进行计数,即可完成链接与点击数的报表,如果还需要其他维度的报表只需要在输出日志的时候带上即可,或者修改日志中间件中的日志范式。
根据上述的流程,笔者写了一个比较简易的短链服务,大家可以开箱即用。
具体启动方式
首先请确保有可用的redis,否则无法顺利启动服务。
git clone https://github.com/mykurisu/shorturl.git cd shorturl npm install npm start
可用配置修改
与短链相关的配置收束在根目录的config.ts
中。
serverConfig: { port: 8000, }, redis: { port: 6379, host: '0.0.0.0', db: 0, }, cacheType: 'redis', defaultHost: 'http://localhost:8000/s', defaultIndex: 'http://localhost:8000/defaultIndex',
配置 | 默认值 | 配置用途 |
---|---|---|
serverConfig.port | 8000 | 服务启动端口 |
redis.port | 6379 | redis端口 |
redis.host | 0.0.0.0 | redis服务地址 |
redis.db | 0 | redis具体储存库表 |
cacheType | redis | 短链储存模式,接受memory/redis |
maxRetryTimes | 5 | 生成短链接最大重试次数 |
defaultHost | http://localhost:8000/s | 短链接前缀 |
defaultIndex | http://localhost:8000/defaultIndex | 短链接失效后重定向地址 |
内置接口
接口路由 | 请求方式 | 接口参数 | 接口用途 |
---|---|---|---|
/s/createUrl | POST | url: string, type?: string | 短链接生成接口 |
/s/deleteUrl | POST | k: string | 删除短链接接口 |
/s/:key | GET | none | 目标链接获取 |
shorturl是有本地储存方案的,也就是说我们是可以监听Redis的状态,如果断开连接时就临时将数据储存到内存中,以达到服务降级的目的。当然我们也可以直接使用内存来储存短链内容,在config.ts
配置中可以进行更改。
让我们脱离短链接这个束缚,其实shorturl本身已经是一个微型存储服务了,我们完全可以进行二次开发,输出更多的模块以支撑更多样的业务。
整个短链接服务其实非常简单,麻烦的是服务的搭建,也就是迈出的第一步。笔者也是在无数次最初一步中挣扎,最终积累了fast-nest这么一个脚手架,希望能帮助到有同样境遇的同学。
另外,附上本文的服务源码 -- shorturl(欢迎大家Star)
更多编程相关知识,请访问:编程教学!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!