Maison  >  Article  >  interface Web  >  Explication détaillée du service de liens courts implémenté par Nodejs+Nest

Explication détaillée du service de liens courts implémenté par Nodejs+Nest

青灯夜游
青灯夜游avant
2021-04-30 10:48:022731parcourir

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.

Explication détaillée du service de liens courts implémenté par Nodejs+Nest

É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 ?

Principe de la chaîne courte

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.

Explication détaillée du service de liens courts implémenté par Nodejs+Nest

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.

Mise en œuvre spécifique

Matériaux : Fast-NestÉchafaudage, Redis

L'ensemble de la mise en œuvre est divisé en 3 parties :

① Recevoir le lien long

@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.

② Générer une clé courte

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(&#39;超过重试次数,请重新生成链接&#39;, 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 :

  • normal - les liens courts normaux expireront dans le délai spécifié
  • une fois - les liens courts uniques expireront automatiquement dans le délai spécifié. expire après avoir été consulté
  • permanent - le lien court à long terme n'expirera pas automatiquement et ne pourra être supprimé que manuellement

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é.

③ Recevez le lien court et terminez la redirection cible

@Get(&#39;/:key&#39;)
@Redirect(Config.defaultIndex, 302)
async getUrl(
        @Param(&#39;key&#39;) 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 === &#39;once&#39;) {
        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é.

Fonctions supplémentaires

Utilisez le système de journalisation pour générer des rapports

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 = &#39;normal&#39;) {
    const urlKey = await this.handleUrlKey();
    const urlID = UUID.genV4().toString();
    const dataStr = JSON.stringify({
        urlID,
        url,
        type
    });
    this.myLogger.log(`createUrl**${urlID}`, &#39;createUrl&#39;, false);
    await this.client.set(urlKey, dataStr, type === &#39;permanent&#39; ? -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 === &#39;once&#39;) {
        await this.client.del(k);
    }
    this.myLogger.log(`getUrl**${urlID}`, &#39;getUrl&#39;, 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类型的日志进行计数,即可完成链接与点击数的报表,如果还需要其他维度的报表只需要在输出日志的时候带上即可,或者修改日志中间件中的日志范式。

使用方式

根据上述的流程,笔者写了一个比较简易的短链服务,大家可以开箱即用。

shorturl(欢迎大家Star⭐️⭐️)

具体启动方式

首先请确保有可用的redis,否则无法顺利启动服务。

git clone https://github.com/mykurisu/shorturl.git

cd shorturl

npm install

npm start

可用配置修改

与短链相关的配置收束在根目录的config.ts中。

serverConfig: {
    port: 8000,
},
redis: {
    port: 6379,
    host: &#39;0.0.0.0&#39;,
    db: 0,
},
cacheType: &#39;redis&#39;,
defaultHost: &#39;http://localhost:8000/s&#39;,
defaultIndex: &#39;http://localhost:8000/defaultIndex&#39;,
配置 默认值 配置用途
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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer