12

使用 Serverless 创建一个简单的短网址服务

 3 years ago
source link: https://my.oschina.net/donhui/blog/4863490
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
up-8f9261d2169305be15f16cefae496c7fcde.png
本文首发于 ServerLife 公众号
短网址服务,是一个能够将冗长的网址转换缩短为更简短、方便的短网址的工具。
经过短网址服务缩短的网址很短很容易使用和传播。
例如我们经常会在营销短信中会看到短网址。
本文将介绍使用 Serverless 创建一个简单的短网址服务。

使用的技术

使用的产品与服务:
  • Serverless Framework:一个免费开源的 Serverless 框架。
  • Tencent SCF:腾讯云云函数服务。
  • Lambda Store:全球第一个 Serverless Redis 服务。
语言及框架:
  • Python 3.6
  • Flask:一个微型的 Python 开发的 Web 框架。

项目初始化

通过 npm 全局安装 Serverless 命令行工具:
npm install -g serverless
使用模板初始化项目:
serverless init flask-starter --name url-shortener

业务设计与实现

这个简单的短网址服务,主要有以下几个接口,目前没有前端页面:
1、将长网址转换为短网址
2、访问短网址时将其重定向到原始的长网址
3、将短网址还原为原始的长网址
数据目前存储到 redis 中,这里用到了 Lambda Store 服务。
在生成短网址时,会生成一个6位的随机标识符(如果标识符已存在,会重新生成,最多尝试20次,如果还是失败,则返回错误信息),然后以 key 为短网址标识符,以 value 为原始的长网址,将其存储到 redis 中。
访问短网址时,首先以标识符为 key 从 redis 获取相应的 原始的长网址,如果获取成功,执行重定向操作,否则返回404。
还原短网址时,也是以标识符为 key 从 redis 获取相应的 原始的长网址,如果获取成功,则返回相应的原始长网址,否则返回错误信息。
已将代码上传到 GitHub: https://github.com/donhui/url-shortener, 核心代码如下:
import random
import string
from flask import Flask, jsonify, request, abort, redirect, render_template
import redis
from settings import redis_settings
app = Flask(__name__)


def generate_identifier(n=6):
    identifier = ""
    for i in range(n):
        identifier += random.choice(string.ascii_letters)
    return identifier


def get_redis_instance():
    return redis.Redis(
        host=redis_settings.get('host'),
        port=redis_settings.get('port'),
        password=redis_settings.get('password'))


redis_instance = get_redis_instance()


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/generate/<path:address>/")
def generate(address):
    identifier = ''
    i = 0
    while True:
        if i == 20:
            break
        identifier = generate_identifier()
        if redis_instance.exists(identifier):
            i = i + 1
            continue
        else:
            break

    if identifier == '':
        return jsonify({"status": "fail", "error_msg": "generate shortened_url fail, please try again."})

    if not (address.startswith("http://") or address.startswith("https://")):
        address = "http://" + address

    redis_instance.set(identifier, address)

    shortened_url = request.host_url + identifier
    return jsonify({"identifier": identifier, "shortened_url": shortened_url})


@app.route("/<string:identifier>/")
def fetch_original(identifier):
    try:
        origin_url = redis_instance.get(identifier)
    except:
        abort(404)
    return redirect(origin_url)


@app.route("/restore/<string:identifier>/")
def restore(identifier):
    try:
        original_url = redis_instance.get(identifier)
    except:
        pass
    if original_url is None:
        return jsonify({"status": "fail", "error_msg": "get original_url fail, please check the identifier."})
    return jsonify({"identifier": identifier, "original_url": str(original_url)})


if __name__ == "__main__":
    app.run(debug=True)
开发完成后,代码目录结构截图如下:
up-7425230028e3bfe1563e84673cb9455e571.png

部署到腾讯云 SCF

使用 serverless deploy 命令即可一键快速将服务部署到腾讯云 SCF。
up-a348ec295503e0dcac5ee57a892ee0267f3.png

访问短网址相关服务

短网址顾名思义网址比较短,一般都会有一个短的域名。
理论上 SCF 支持自定义域名,当然最好是个短域名。
下面的  Demo 出于演示的目的,权且使用腾讯云自带的 API 网关地址。
首先进入首页:
up-b1d8f7d753f0395abf56d662dd30d01ccc5.png
生成一个短网址:
up-3a700e75c14799e0095e489d4ff0644ac3a.png
生成这个短网址后,使用浏览器访问它,它会跳转到原始的网址。
还原短网址:
up-bc93a3e55db702a219b6511349454137f09.png

总结

本文使用 Serverless 创建了一个简单的短网址服务。用到了 Serverless Framework 及其组件 tencent-flask,还用到了 Lambda Store 服务,创建了一个完完全全的 Serverless 服务。
当然从功能的角度来讲,还有很多可以优化的地方,比如:友好的前端页面、更友好的提示、更好的标识符生成算法等等。

参考

© 著作权归作者所有

portrait.gif

其他人还在看

本文收录在 GitHub 地址 https://github.com/chengxy-nds/Springboot-Notebook 时间格式化在项目中使用频率是非常高的,当我们的 API 接口返回结果,需要对其中某一个 date 字段属性进行特殊的格式化处理,通常会...
引言 CAP 理论,相信很多人都听过,它是指: 一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。 为什么要理解 CAP 理论?我能说...
JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一。那么如何在JS中实现继承呢?让我们拭目以待 JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如下: // 父类 function Perso...
抛开业务谈技术都是在耍流氓。—— Kevin Wan 为什么需要缓存? 先从一个老生常谈的问题开始谈起:我们的程序是如何运行起来的? 程序存储在 disk 中 程序是运行在 RAM 之中,也就是我们所说的 main memory 程序的...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK