「Serverless云开发72变」随时随地短链

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
函数计算FC,每月15万CU 3个月
简介: 你有没有发现,我们的任务中出现长 URL 就会比较麻烦?在微博这些限制字数的应用里。好处不言而喻。短、字符少、美观、便于发布、传播。如果有一个短址生成器就好了。市面上越来越多产品下线,如某杜的dmz仅限于为企业用户提供服务;新浪则不对外提供他t.cn等。利用这个机会尝试一下简单的 Web 全栈开发。

> 阿里云云开发平台,让每一个创新变成可能 <

Servreless运行过程

image.png

开发背景

你有没有发现,我们的任务中出现长 URL 就会比较麻烦?在微博这些限制字数的应用里。好处不言而喻。短、字符少、美观、便于发布、传播。如果有一个短址生成器就好了。市面上越来越多产品下线,如某杜的dmz仅限于为企业用户提供服务;新浪则不对外提供他t.cn等。利用这个机会尝试一下简单的 Web 全栈开发。

思考

本人是就读云计算技术与与应用,学的东西主要偏向服务器相关运维,此次选择Serverless云开发Fass想看下与传统开发与运维有什么区别。

开发

云开发代码: codeup.aliyun 仓库
欢迎小伙伴提建议和共同改进

image.png

设计思路

当我们在浏览器里输入 https://url.catni.cn/ARJreq

  1. DNS首先解析获得 url.catni.cn 的 IP 地址
  2. DNS 获得 IP 地址以后(比如:127.0.0.1),会向这个地址发送 HTTP GET 请求,查询短码 ARJreq
  3. https://url.catni.cn/ 服务器会通过短码 ARJreq 获取对应的长 URL
  4. 请求通过 HTTP 302 转到对应的长 URL https://workbench.aliyun.com/

*这里有个小的知识点,为什么要用 302 跳转而不是 301 呐?

301 是永久重定向,302 是临时重定向。短地址一经生成就不会变化,所以用 301 是符合 http 语义的。同时对服务器压力也会有一定减少。
但是如果使用了 301,我们就无法统计到短地址被点击的次数了。而这个点击次数是一个非常有意思的大数据分析数据源。能够分析出的东西非常非常多。所以选择302虽然会增加服务器压力,但是我想是一个更好的选择。

主要函数设计

from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect
from .models import urlList
from .common.utils import json_response
from .common.arithmetic import ShortUrlGenerator
import os

# Create your views here.
def index(request):
    return render(request, 'indexview/index.html')


def generate(request):
    '''
    短链生成
    :param request:
    :return: data
    '''
    sourceUrl = request.GET.get('sourceUrl')
    shortUrl = ShortUrlGenerator(sourceUrl)
    sourceUrlCheck = urlList.objects.filter(sourceUrl=sourceUrl)
    if sourceUrlCheck.count() == 0:
        safetyCheckFlag = safetyCheck(sourceUrl)
        if safetyCheckFlag == '未发现威胁':
            primaryKey = shortUrl.shortUrl()[1]
            urlList.objects.create(sourceUrl=sourceUrl, primaryKey=primaryKey)
            flag = True
        else:
            return json_response(code=-1, msg=f'该网址存在分析:{safetyCheckFlag},不给予申请短链')
    else:
        primaryKey = urlList.objects.get(sourceUrl=sourceUrl).primaryKey
        flag = False
    data = {
        'flag': flag,
        'sourceUrl': sourceUrl,
        'primaryKey': primaryKey
    }
    print(data)
    return json_response(code=0, msg='获取成功!', data=data)


def safetyCheck(url):
    '''
    链接安全性检测
    :param url
    :return 链接安全性
    '''
    import requests
    main = ['未发现威胁', '未发现威胁', '未发现威胁', '欺诈', '风险', '违法']
    url = 'http://api.anquan.baidu.com/bsb/lookup?url=' + url
    headers = {
        'apikey': os.environ['BD_apikey']
    }

    res = requests.get(url, headers=headers).json()['result'][0]['main']
    return main[res]


def open(request, primaryKey):
    '''
    302跳转
    '''
    sourceUrl = urlList.objects.get(primaryKey=primaryKey).sourceUrl
    return redirect(sourceUrl)

路由设计

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('generate', views.generate, name='generat'),
    path('<str:primaryKey>', views.open, name='open'),
]

服务依赖

前端使用原生的html进行开发(bootstrap,axios)
后端当然是选择入门友好的框架了Django

算法实现

实现原理:将长串(或者长串+冲突次数)用MD5生成32位摘要信息,每两位为定义字符数组长度做与操作得到定义字符数组的下标值,取对应的字符,生成16位的特殊字符,取其中的N位做为短串返回。

该算法来源于微博[原始的算法是C# 版本,我只是对其改写成python版本]

import hashlib


class ShortUrlGenerator:
    '''
    :param url
    :return 4组短链数组
    '''

    def __init__(self, url):
        self.url = url

    def shortUrl(self):
        key = "HiramUrl"
        chars = ["a", "b", "c", "d", "e", "f", "g", "h",
                 "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
                 "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
                 "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
                 "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
                 "U", "V", "W", "X", "Y", "Z"
                 ]
        sMD5EncryptResult = hashlib.md5((key + self.url).encode("utf8"))
        hexString = sMD5EncryptResult.hexdigest()
        resUrl = []
        for i in range(4):
            # 把加密字符按照 8 位一组 16 进制与 0x3FFFFFFF 进行位与运算
            sTempSubString = hexString[i * 8: (i + 1) * 8]
            hex16 = '0x' + sTempSubString
            lHexLong = 0x3FFFFFFF & eval(hex16)
            outChars = ""
            for j in range(6):
                # 把得到的值与 0x0000003D 进行位与运算,取得字符数组 chars 索引
                index = 0x0000003D & lHexLong
                # 把取得的字符相加
                outChars += chars[index]
                # 每次循环按位右移 5 位
                lHexLong = lHexLong >> 5

            # 把字符串存入对应索引的输出数组
            resUrl.append(outChars)
        return resUrl


如有小伙伴有更好的想法来实现这部分,可以在下方留言

后期功能扩展

检测:鉴别用户是否输入了不合法的链接(目前已接入某度的网址安全检测),如有则上报网安等措施
接口:采用DRF(Django REST framework)规范相关接口
自定义:设置自定义后缀,访问密码等
统计:点击量、访问的 ip 地域、用户使用的设备
当拥有一定的数据基础后,可进行大数据开发分析,这将是一部巨大的财富

迁移应注意的地方

  1. Q: 由于打包上传环境需要将第三方包一起打包,在安装包时,都要装在项目根目录,目录会显示非常的混乱,建议本地开发完后上传至云平台部署。

    A: 目前暂时还没有有效的解决方案。最合理的是通过pythonpath设置三方包的路径,可是目前fc环境无法设置动态的环境变量,比如

PYTHONPATH=${PWD}/modules

  1. 根据README和文档:Python Django 应用迁移方案
    文档中在上传你的 Django 应用时,是将默认startproject后进入该项目的文件进行上传,然而在项目开发中完全不会采用这种方法进行操作,解决方案是

    配置应用入口,打开 serverless_config.py 文件,更新 FRAMEWORK 配置
    
    FRAMEWORK = {
            'module': 'DJANGO_SETTINGS_MODULE文件,一般settings.py,不要加 .py 后缀'
    }
    
    重要:将module设置为 项目名.settings
  2. 不支持使用db.sqlite3,这就是serverless模式和paas区别,计算资源必须是无状态
  3. 然后我就是用阿里的RDS-mysql数据库进行数据迁移,需使用独立出口IP 注意:不要使用0.0.0.0/0,这并不安全
  4. django后台不能正常登陆到后台,原因未知

小结

  1. 在 serverless 里, 资源的所有权被压缩到一个函数的执行期间内, 资源利用率更高, 费用也就更便宜。 特别适用于小流量用户或流量分布很不均衡的用户。
  2. 采用b/s模式,打开浏览器就能0成本开发,一键部署应用。CloudIDE内置Node.js、Java、Python、PHP等常见环境,省去繁琐的配置工作,让您只需专注于业务逻辑的开发。同时提供免费的云上开发和测试环境以及测试域名,还支持多个小伙伴在线协同,随时随地无缝开发。
  3. 云开发平台提供的 Cloud-Native 集成研发环境支持本地研发和在线研发模式,支持云上测试环境,预发环境,正式环境三套环境的部署。可以更好的提供单元测试,冒烟测试等常规上限流程。👍👍👍
  4. 至于免运维,虽然节省了不少环境的部署,但还有点距离(目前看来市场还是需要运维人员的,hhh), 相比在架构上的灵活性,平台可迁移性上的损失,可以忽略不计。
  5. serverless是趋势,但在项目框架这方面还是要下功夫。

还没有使用过Serverless云开发?

现在花3分钟体验新手任务即领10元阿里云无门槛代金券。
ServerlessImage Serverless

本文参加Serverless云开发的有奖征文活动,已经获得作者授权

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
10月前
|
运维 Serverless 云计算
云上开发新范式:Serverless 的必然与应然 | 云栖深度对话
云上开发新范式:Serverless 的必然与应然 | 云栖深度对话
|
11月前
|
监控 Serverless 测试技术
函数计算的开发
函数计算的开发
52 0
|
弹性计算 监控 安全
函数计算进阶-IP查询工具开发
本场景介绍如何使用函数计算服务开发一个IP查询工具。
113 0
|
17天前
|
前端开发 大数据 数据库
🔥大数据洪流下的决战:JSF 表格组件如何做到毫秒级响应?揭秘背后的性能魔法!💪
【8月更文挑战第31天】在 Web 应用中,表格组件常用于展示和操作数据,但在大数据量下性能会成瓶颈。本文介绍在 JavaServer Faces(JSF)中优化表格组件的方法,包括数据处理、分页及懒加载等技术。通过后端分页或懒加载按需加载数据,减少不必要的数据加载和优化数据库查询,并利用缓存机制减少数据库访问次数,从而提高表格组件的响应速度和整体性能。掌握这些最佳实践对开发高性能 JSF 应用至关重要。
30 0
|
2月前
|
运维 Serverless API
Serverless 应用引擎使用问题之如何开发HTTP服务
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
1月前
|
监控 Serverless Go
Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
|
1月前
|
Java Serverless Go
Golang 开发函数计算问题之在 Golang 中避免 "concurrent map writes" 异常如何解决
Golang 开发函数计算问题之在 Golang 中避免 "concurrent map writes" 异常如何解决
|
1月前
|
Serverless Go
Golang 开发函数计算问题之defer 中的 recover() 没有捕获到 如何解决
Golang 开发函数计算问题之defer 中的 recover() 没有捕获到 如何解决
|
2月前
|
监控 IDE Java
函数计算产品使用问题之如何不使用FC的IDE进行开发,并将开发好的应用部署到FC上
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
3月前
|
运维 前端开发 Serverless
云开发如何解决serverless对端的最后一公里问题
云开发如何解决serverless对端的最后一公里问题

热门文章

最新文章

相关产品

  • 函数计算