Heim > Artikel > Web-Frontend > Detaillierte Erläuterung des von Nodejs+Nest implementierten Kurzlink-Dienstes
In diesem Artikel wird Ihnen die Methode zur Implementierung eines Kurzlink-Dienstes basierend auf dem Node-Framework Nest vorgestellt. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.
Empfohlenes Lernen: „nodejs-Tutorial“
Jedes Mal, wenn ich zum Springen klicke, wird sich der Autor großartig fühlen zu Was führt zur richtigen Seite?
Das Prinzip der kurzen Links besteht darin, kurze Links zu verlängern. Wie kann also diese kurze Zeichenfolge in eine lange Zeichenfolge umgewandelt werden? Verlässt es sich auf einen magischen Verschlüsselungsalgorithmus? Nein, wir müssen uns nur auf die Schlüssel/Wert-Zuordnungsbeziehung verlassen, um diese scheinbar magische Sache leicht zu erreichen. Mit einem Bild kann jeder den gesamten Prozess des Zugriffs auf den Kurzlink deutlich erkennen.
Zuerst erhalten wir durch die Verarbeitung des Kurzlink-Dienstes normalerweise eine URL mit nur einer Verzeichnisebene, und dann können wir die erhaltene URL verteilen.
Dann gelangen wir auf die Benutzerseite. Nachdem der Benutzer auf den Kurzlink geklickt hat, gelangt er als Erstes nicht zur Zielseite, sondern zum Kurzlink-Dienst.
Der Kurzlink-Dienst fängt den Pfadnamen auf dem Link ab und verwendet ihn als Schlüssel, um den entsprechenden Wert in der Zuordnungsbeziehung zu finden.
Wenn der entsprechende Wert nicht gefunden werden kann, bedeutet dies, dass der Kurzlink nicht existiert oder abgelaufen ist. Wenn die Abfrage erfolgreich ist, führt der Kurzlink-Dienst direkt eine 302-Verbindung zum Ziellink im Wert durch, um einen Kurzlink-Zugriff abzuschließen.
Spezifische Implementierung
Materialien:Fast-NestDie gesamte Implementierung ist in drei Teile unterteilt:
① Empfang langer Links
@Post('/createUrl') async createUrl( @Body('url') url: string, @Body('type') type: string, ) { const shortUrl = await this.shorturlService.createUrl(url, type); return { shortUrl, }; }
createUrl
im Dienst >Schnittstelle, empfangen Sie die Felder url
und type
und übergeben Sie sie an shorturlService
, warten Sie, bis der Kurzlink generiert und dann ausgegeben wird. 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; }
createUrl
接口,接收url
已经type
字段,并将其传入shorturlService
中,等待短链接生成然后输出。
@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; }
首先通过Math.random().toString(36).slice(-4)
获取4位随机字符串,这个将会作为短链的pathname。
在进行映射之前,我们需要对其进行唯一性判断,虽然出现的可能性不大,但是还是需要防范短链覆盖这类的问题。本服务的解决方案是重试生成,如果短链值不幸重复时将会进入重试分支,服务将会内置可重试次数,如果重试的次数超过配置的字数,本次转换将会返回失败。
除了url
,createUrl
方法还接受一个type
字段,这里涉及特殊短链的特性。我们短链有三种模式:
生成urlKey
之后,将会与type
一起转成字符串储存到redis中,并输出拼接好的短链接。
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}`; }
用户侧会获得一个类似http://localhost:8000/s/ku6a
的链接,点击之后相当于是给短链接服务发送了一个GET请求。
服务接收到请求之后获取链接中key字段的值,也就是ku6a
这个字符串,利用它查找Redis中的映射关系。
这里有两个分支,一个是在Redis中无法查询到相关的值,服务则认为短链接已经失效会直接return,因为getUrl
返回了空值,重定向装饰器会将本次请求重定向到默认的目标链接中。
如果在Redis中顺利查到相关的值,则会读取其中的url
和type
Erhalten Sie zunächst eine 4-stellige Zufallszeichenfolge über Math.random().toString(36).slice(-4)
, dies wird als Pfadname des Kurzlinks verwendet.
url
akzeptiert die Methode createUrl
auch ein Feld type
, das die Eigenschaften spezieller Kurzlinks beinhaltet. Wir haben drei Modi für Kurzlinks: Nach der Generierung von urlKey
wird er verglichen mit type werden in Strings umgewandelt und in Redis gespeichert, und der gespleißte Kurzlink wird ausgegeben.
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; }Die Benutzerseite erhält ein ähnliches Bild wie
http://localhost:8000/s/ku6a Code> Nach dem Klicken auf den Link entspricht dies dem Senden einer GET-Anfrage an den Kurzlink-Dienst. <p><strong>Nach Erhalt der Anfrage ruft der Dienst den Wert des Schlüsselfelds im Link ab, bei dem es sich um die Zeichenfolge <code>ku6a
handelt, und verwendet ihn, um die Zuordnungsbeziehung in Redis zu finden. Hier gibt es zwei Zweige: Der Dienst geht davon aus, dass der Kurzlink abgelaufen ist, und kehrt direkt zurück, da getUrl
einen Nullwert und den Umleitungsdekorator zurückgibt leitet diese Anfrage an den Standardziellink weiter. 🎜🎜Wenn der relevante Wert erfolgreich in Redis gefunden wird, werden die Felder url
und type
gelesen. Wenn der Typ einmal ist, bedeutet dies, dass es sich um einen einmaligen Link handelt Die Löschmethode wird aktiv ausgelöst und der Ziellink wird schließlich zurückgegeben. 🎜🎜Zusätzliche Funktionen🎜🎜Verwenden Sie das Protokollsystem zur Ausgabe von Berichten🎜🎜Bei der Verwendung von Kurzlinks besteht eine hohe Wahrscheinlichkeit, dass relevante Datenstatistiken benötigt werden, ohne eine Datenbank zu verwenden. 🎜🎜Mit diesem Service können wir den Bericht über den Kurzlink-Zugriff noch am selben Tag ausfüllen, indem wir die Landeprotokolldateien scannen. 🎜🎜Fügen Sie das Feld 🎜urlID🎜 hinzu, wenn Sie Kurzlinks zur statistischen Differenzierung generieren und Protokolle aktiv ausgeben, wie folgt: 🎜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)
更多编程相关知识,请访问:编程教学!!
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des von Nodejs+Nest implementierten Kurzlink-Dienstes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!