Nodejs+Nestで実現するショートリンクサービスの詳細説明

青灯夜游
リリース: 2021-05-06 09:35:47
転載
2824 人が閲覧しました

この記事では、NodeフレームワークNestをベースとしたショートリンクサービスの実装方法を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

Nodejs+Nestで実現するショートリンクサービスの詳細説明

推奨学習: 「nodejs チュートリアル

私たちは日常生活の中であらゆる種類の奇妙な短いリンクを目にすることがあります。クリックしてジャンプするたびに魔法のような気分になります。この短いリンクはどのようにしてユーザーを正しいページに誘導するのでしょうか?

ショートチェーンの原則

ショートチェーンの原則は、短いブログを長くすることですでは、この短い文字列をどのようにして長い文字列に変えることができるのでしょうかリンクの?何か魔法のような暗号化アルゴリズムに依存しているのでしょうか?いいえ、キーと値のマッピング関係に依存するだけで、この一見魔法のような 短い作業を長くする を簡単に実現できます。

画像を使用すると、短縮リンクにアクセスするプロセス全体を誰でも明確に見ることができます。

Nodejs+Nestで実現するショートリンクサービスの詳細説明

まず、ロングリンクを用意します。ショートリンクサービスの処理により、通常はディレクトリが 1 層しかない URL が出力されます。取得したURLを配布します。

次にユーザー側に移りますが、ユーザーがショートリンクをクリックした後、最初に到達するのは目的のページではなく、ショートリンクサービスです。

ショート リンク サービスは、リンク上のパス名をインターセプトし、それをキーとして使用して、マッピング関係内の対応する値を見つけます。

対応する値が見つからない場合は、ショート リンクが存在しないか期限切れであることを意味します。クエリが成功すると、ショート リンク サービスは値内のターゲット リンクに直接 302 アクセスして、クエリを完了します。ショートリンクアクセスです。

具体的な実装

マテリアル: Fast-NestScaffolding、Redis

実装全体は 3 つの部分に分かれています:

① 長いリンクを受信する

@Post('/createUrl')
async createUrl(
    @Body('url') url: string,
    @Body('type') type: string,
) {
    const shortUrl = await this.shorturlService.createUrl(url, type);
    return {
        shortUrl,
    };
}
ログイン後にコピー

サービス内に createUrl インターフェイスを作成し、url フィールドと type フィールドを受信します。 add shorturlService に渡され、ショートリンクが生成されるのを待って出力します。

② shortKey の生成

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;
}
ログイン後にコピー

まず、Math.random().toString(36).slice(-4) を通じて 4 桁のランダムな文字列を取得します。短いリンクとしてのパス名。

マッピングの前に、その一意性を判断する必要があります。可能性は低いですが、それでも、チェーン カバレッジが短いなどの問題を防ぐ必要があります。このサービスの解決策は、生成を再試行することです。残念ながら短いチェーン値が繰り返された場合、再試行分岐に入ります。サービスには再試行回数が組み込まれています。再試行回数が構成された単語数を超える場合、この変換は失敗を返します。

createUrl メソッドは、url に加えて、特殊な短いリンクの特性を含む type フィールドも受け入れます。私たちのショートリンクには 3 つのモードがあります:

  • normal - 通常のショートリンクは指定された時間内に期限切れになります
  • once - 1 回限りのショートリンクは指定された時間内に期限切れになります。アクセス後に期限切れになります
  • 永続 - 長期の短いリンクは自動的に期限切れにならず、手動での削除のみを受け付けます

urlKey を生成した後は、同じになります。 as type を文字列に変換してredisに格納し、繋ぎ合わせたショートリンクを出力します。

③ 短いリンクを受け取り、ターゲットのリダイレクトを完了します。

@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;
}
ログイン後にコピー

ユーザー側は、http://localhost:8000/s/ku6a のようなリンクを取得します。クリック後 ショートリンクサービスにGETリクエストを送信するのと同じです。

リクエストを受信した後、サービスはリンク内のキー フィールドの値 (文字列 ku6a) を取得し、それを使用して Redis 内のマッピング関係を検索します。

ここには 2 つの分岐があります。1 つは、Redis で関連する値をクエリできないことです。サービスは、短いリンクの有効期限が切れたと判断し、getUrl が null 値を返し、デコレータは、このリクエストをデフォルトのターゲット リンクにリダイレクトします。

関連する値が Redis で正常に見つかった場合、url フィールドと type フィールドが読み取られます。type が 1 回の場合、これは 1 つであることを意味します。リンクは削除メソッドをアクティブにトリガーし、最終的にターゲット リンクを返します。

追加機能

ログ システムを使用したレポート出力

短いリンクを使用する場合、関連するデータ統計が必要になる可能性が高くなります。データベースを使用していますか?統計についてはどうですか?

本サービスでは、ランディングログファイルをスキャンすることで、ショートリンクアクセスのレポートを即日完了することができます。

短いリンクを生成するときは、次のように統計微分用の urlID フィールドを追加し、積極的にログを出力します。

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)

更多编程相关知识,请访问:编程教学!!

以上がNodejs+Nestで実現するショートリンクサービスの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート