专栏首页articleSCF VS Code 实践:开发网址导航
原创

SCF VS Code 实践:开发网址导航

概述

开发一个网址导航来实践腾讯云无服务器函数的功能,总结期间碰到的一些小坑。

前期准备

什么是 SCF ?我们能利用 SCF 做什么?serverless 要怎么用?优势是什么? 不足点又是什么?

对于想尝鲜无服务器函数功能的小伙伴前期要有一定的知识储备,没有银弹,合适的才是最好的。

文档指南

初期看文档,看看腾讯云无服务器函数支持哪些语言和响应的版本,函数和函数能否相互调用(可以调用)等,了解腾讯云给出的功能范围,确定我能通过这些功能做什么事。别忘了还有计费模式,你得知道是怎么扣费的!

思考🤔

对于 serverless 的应用场景目前只要是在以下几个方面:

  1. 事件请求场景
  2. 流量突发场景
  3. 处理大数据场景

同时推荐具备无状态的特性,对于网址导航这个功能,页面偏静态,接口调用少,我需要

  1. 一个定时服务来下载对应网址的 favicon 文件
  2. 收集用户的投稿链接
  3. 页面加载时获取内容

基本功能包含增删改查,除了查询,其他的功能我也不需要权限,管理员自己就能 cover 掉,不和其他业务强绑定关联,模块自身独立,除非后续迭代,当前的应用场景是匹配 serverless 能力的。

整体架构

其实可以做的功能还有很多,但不一定是刚需,目前只要满足最基本的使用即可。

定时任务的频率

现实场景中,Favicon 的变动频度是很小的,所以只需要一个定时任务就可以实现。

由于函数的执行时间也是有限制的,理想情况下一次图片抓取主要取决于「网站能否被打开」,因为部分网站可能会被“特殊照顾”,只考虑国内的一些网站的话,执行时间控制在 5 秒以内还是绰绰有余的。

但你还是无法保证每次从数据库中取出的这些链接都能被执行完,实际情况也确实是不可能完成,所以我们需要在定时的基础上,人为的做一个控制:判断上一次修改时间距离当前时间是否大于N(单位可以是天,也可以是小时,分钟),这样函数被定时启动的时候只下载之前没有被 Download 的网页图标。

关键代码:

exports.main_handler = async (event, context, callback) => {
    const lists = await sqlAction.query('select * from tableName where deleted=0');
    const during =  60 * 60 * 24 * 5 * 1000; // 5 天
    for (const item of lists) {
        const past = new Date(item.update_time).getTime();
        const now = new Date().getTime();
        if (now - past >= during || isNaN(past)) {
            const fileName = await download(item.link, item.name);
            if (fileName) {
                await sqlAction.query(`update tableName set favicon='${fileName}', update_time='${helper.formatDate(new Date().getTime())}' where id=${item.id}`);
            }
        }
    }
    return 'success';
};

COS 存储

定时任务抓取的小图标需要保存到 cos 上作为静态资源,这里我并没有使用腾讯云的服务,因为某🐂的 http 访问有免费额度,所以我使用 ta 来上传抓取的资源,因为是定时抓取,所以需要对文件可覆盖,不能使用随机ID命名的方式,否则资源会越来越多,后期还要做清理。使用其他云存储的也是同理。

上传代码:

const mac = new qiniu.auth.digest.Mac(qiniu.ak, qiniu.sk);
const config = new qiniu.conf.Config();
// 空间对应的机房
config.zone = qiniu.zone.Zone_z1;
// 是否使用https域名
config.useHttpsDomain = true;
// 上传是否使用cdn加速
config.useCdnDomain = true;

// 这种配置方式可以相同文件名覆盖
const options = {
    scope: 'bucketName:' + name,
};

const putPolicy = new qiniu.rs.PutPolicy(options);
const uploadToken = putPolicy.uploadToken(mac);

const formUploader = new qiniu.form_up.FormUploader(_config);
const putExtra = new qiniu.form_up.PutExtra();
const path = process.cwd() + '/icons/' + name;
// 文件上传
formUploader.putFile(uploadToken, name, path, putExtra, function (respErr, respBody, respInfo) {
    if (respErr) {
        reject(respErr);
        throw respErr;
    }
    if (respInfo.statusCode == 200) {
        resolve(respBody)
    } else {
        reject(respBody)
    }
});

静态页面

对于单页应用是可以放在任意的静态服务器上,或者 CDN 上,但是对于有 SEO 要求的网页来说,服务端渲染是少不了的,这里使用了相对简单的方式。

函数调数据库读取内容,NodeJs 使用 ejs 引擎来渲染。

渲染代码:

let html = fs.readFileSync(path.resolve(__dirname, './index.html'), {
    encoding: 'utf-8'
});
html = Ejs.render(html.toString(), {
    title: 'Nox导航 - 互联网从这开始',
    list: result
});

return {
    isBase64Encoded: false,
    statusCode: 200,
    headers: { 'Content-Type': 'text/html' },
    body: html
}

反向代理

由于部署好的页面只有一个访问路径,如果使用二维码分享的话就无所谓了,但是要对外服务的话这个路径暴露出去就不太合适了,需要用 Nginx 做一次代理。

代理设置:

location /daohang {
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_redirect https://service-8nvzq5f1-1251487239.ap-shanghai.apigateway.myqcloud.com/release/navigation-index  /;
    proxy_set_header Accept-Encoding "";
    proxy_set_header User-Agent $http_user_agent;
    proxy_set_header Accept-Language "zh-CN";
    proxy_connect_timeout      240;
    proxy_send_timeout         240;
    proxy_read_timeout         240;
    # note, there is not SSL here! plain HTTP is used
    proxy_pass https://service-8nvzq5f1-1251487239.ap-shanghai.apigateway.myqcloud.com/release/navigation-index;
    sub_filter_once off;
}

最后我们可以使用 https://www.noxxxx.com/daohang 来访问了!

注意点

1. 部署 html 页面,需要开启集成响应功能,否则返回的内容不能被识别为 html。

2. Mysql 调用后需要 destroy 掉,否则整个函数运行会超时。

3. 本地调试运行函数后报异常,抛出的错误信息没有具体的代码行数,通常需要优先检查自己的代码逻辑是不是有问题,比如说取对象属性名时,对象为空的情况,也会有类似下面的这种错误,单看报错日志看不出什么...

4. 远程访问 Mysql 服务需要开启权限,如何创建 Mysql 用户,基于 Docker 下的 Nginx 转发 MySQL 连接

总结

通过腾讯云的 scf 插件结合 visual studio code,无服务器函数在开发过程中,只需要聚焦业务功能的实现,同时,本地可以近乎一键部署到线上,效率非常高,运维部署层面上可以节省很多时间和精力。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 直接选择排序算法

    qubianzhong
  • 使用TCGAbiolinks下载TCGA的数据

    TCGAbiolinks是一个分析处理TCGA数据的R包,通过GDC API来查询和下载TCGA的数据,同时提供了差异分析,生存分析,富集分析等常见的分析功能,...

    生信修炼手册
  • Markets and Markets:2022年手势控制装置市场总产值将达340亿美元

    VRPinea
  • Python原地输出效果实现

    由于 GIL 的存在,所以每次只有一个线程在运行,所以 slow_function() 的作用就是强制 sleep 主线程,使子线程得到执行

    用户7685359
  • 经典设计模式(二):单例模式

    单例模式确保一个类只有一个实例,并提供一个全局访问点,上班偷偷写的文章,所以请仔细看注释

    低调小熊猫
  • 今日分享: 常用工具集

    双鬼带单
  • Eos测试框架EosFactory

    EOS Factory包含一个完整的EOS测试框架,可以进行智能合约的开发和测试。由Tokenika于创建于2017年的这个基于Python的EOS测试框架可以...

    用户1408045
  • 爬虫实战 : 爬虫之 web 自动化终极杀手(下)

    最近写了好几个简单的爬虫,踩了好几个深坑,在这里总结一下,给大家在编写爬虫时候能给点思路。本次爬虫内容有:静态页面的爬取。动态页面的爬取。web 自动化终极爬虫...

    serena
  • Win10系统C盘爆满解决之自带设置

    但是用快捷键会显得你更"专业"不是么?后面小编还会和大家分享各种工作和学习上面的小技巧,大家多多关注哦~

    云深无际
  • 如何在Ubuntu 14.04上安装Bacula-Web

    Bacula-Web是一个PHP Web应用程序,它提供了一种查看已经运行的Bacula备份作业的摘要和图形的简便方法。虽然它不允许您以任何方式控制Bacula...

    灬半痴

扫码关注云+社区

领取腾讯云代金券