阿里云函数计算 + Aglio 实现 API Blueprint markdown 渲染

本文涉及的产品
函数计算FC,每月15万CU 3个月
简介: 这次想聊聊我在写的站里的一个核心的功能——API 文档的编辑与展示。我最初的想法是,使用 Markdown 来编写文档。但是这样在格式上难免不好统一。跟 @BillSJC 聊的时候,他向我推荐了 Swagger 和 API Blueprint。

本文首发于我的博客 阿里云函数计算 + Aglio 实现 API Blueprint markdown 渲染

这次想聊聊我在写的站里的一个核心的功能——API 文档的编辑与展示。我最初的想法是,使用 Markdown 来编写文档。但是这样在格式上难免不好统一。跟 @BillSJC 聊的时候,他向我推荐了 Swagger 和 API Blueprint。这两个都是 API 文档自动生成工具。对比过后,我决定选择 API Blueprint,因为它是使用类似 markdown 的语法进行文档编写的,相比 Swagger 的使用 YAML,API Blueprint 写的 markdown 可读性更强一些:

# GET /message
+ Response 200 (text/plain)

        Hello World!

地鼠不友好

API Blueprint 的官网上 https://apiblueprint.org/ 推荐了从文档编辑到解析、渲染的诸多工具支持。
我的需求是找到一个 API Blueprint 的渲染工具,将我在 Apicon 编写的 markdown 渲染转换成 HTML 文档。但官网展示的这些工具大多都是 Node.js 编写的,我并没有找到支持 Golang 的工具。但我又不想额外在服务器上再维护一个容器,用于专门运行转换 markdown 的 Node.js 代码。
这时,@BillSJC 向我介绍了 Serverless 的概念,同时推荐了阿里云的函数计算。

Serverless?

从字面上意思来理解 Serverless,即无服务器。
将这个概念放在阿里云的函数计算服务上,即我只需要将我实际的业务代码上传到函数计算服务上,然后通过约定好的触发器去调用这个服务。在这其中,我并不需要去关心服务器相关的硬件配置,环境配置,以及运维等这些事情。我只需要专注于业务代码即可。
这可能和我们平时做的 RESTful API 有些相似,RESTful API 其实也可以看做是通过一个 HTTP 触发器,去调用相关服务。虽然二者的最终结果都是一样的,但 RESTful API 的背后,往往是我们的服务器一直在监听是否有请求,一旦有请求来了,就进行处理;而函数计算这个“事件驱动”更像是一个被动的东西,被触发后执行一段事先设定好的步骤,然后结束。

就像一个函数一样,每次执行都是差不多的步骤和内容,前后之间的两次调用并不会有太大的关联和影响。我们可以来看下大厂都在用它在干什么:

新浪微博 - 调用函数将用户上传的图片进行个性化处理
115 - 触发函数对用户上传的日志进行压缩、转换
芒果 TV - 触发函数记录视频文件的属性信息
石墨文档 - 使用函数来处理多用户文档编辑的冲突

这么一看我是选对了,新浪都用来处理图片了,那我用来处理 markdown 岂不也是合情合理?嘛,开始吧!

Aglio 渲染 markdown

API Blueprint 的渲染器我之所以选择 Aglio https://github.com/danielgtaylor/aglio ,是因为它不仅可以自定义主题,还可以自定义模板。这样我就可以将页面中我不需要的标题、导航栏等内容删除,仅保留内容主体。同时 Aglio 不仅支持 CLI 使用,还可以当做一个包,放在项目中调用。
我们先在本地实现一个 markdown 的渲染,再将它改写成函数计算的模式。

先把 Aglio 给拉下来:

yarn add aglio

然后我们就可以开始编写主要的代码了:

let aglio = require('aglio')
let blueprint = `
# GET /message
+ Response 200 (text/plain)
        Hello World!
`

options = {
    themeTemplate: 'index.jade'
};

aglio.render(blueprint, options, function (err, html, warnings) {
    if (err) return console.log(err);
    if (warnings) console.log(warnings);
    console.log(html);
});

这里我使用的是 Aglio 的默认主题,你可以在 Aglio GitHub Repo 的olio-theme分支下载到主题需要的index.jademixins.jade这两个模板文件。然后就可以开始魔改这两个jade文件了:

doctype

include mixins

html
    head
        meta(charset="utf-8")
        style!= self.css
    body.preload
        div
            .row
                .content
                    block content
                        +Content('primary', false)

我这边将导航栏,标题栏、不用的 JavaScript 都去掉了。然后mixins.jade也是按需修改,相关英文的提示我也进行了汉化。最后的效果是这样的:

下面我们来将其部署到阿里云函数计算上。

部署到阿里云函数计算

因为我们这里的文件很多,故使用阿里云提供的fun工具来进行部署。
Mac 安装fun

brew install fun

安装好后,先输入fun config来跟着命令行提示进行基本的设置:

Aliyun Account ID (阿里云ID)
Aliyun Access Key ID ***************    (AK)
Aliyun Secret Access Key ***************    (SAK)
Default region name cn-hongkong        (地区,我是选择跟自己轻量应用一样的地区,方便直接内网调用)
The timeout in seconds for each SDK client invoking 300        (上传代码超时时间)
The maximum number of retries for each SDK client 3        (上传失败后的尝试次数)
Allow to anonymously report usage statistics to improve the tool over time? No        (是否帮助阿里云改进此工具)

有坑注意
第一项Aliyun Account ID填写的是阿里云的账号 ID,并不是登录时填写的账号。账号 ID 可以在基本资料-安全设置中找到。

之后就可以执行fun init来初始化一个服务了。它会给我们创建template.yml文件,我们进行如下配置:

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  Aglio-Function:
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'Markdown render'
    Aglio-Function:
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: index.handler
        Runtime: nodejs8
        CodeUri: './'
      Events:
        http-test:
          Type: HTTP
          Properties:
            AuthType: ANONYMOUS
            Methods: ['POST']

注意这里的Events,即创建了一个 HTTP 触发器,仅允许使用 POST 进行调用,且不做鉴权。

有坑注意
在所有触发器中,HTTP 触发器只能在创建服务时添加,之后无法再添加。因此,在使用fun部署项目时,我们通过template.yml文件创建。

下面编写index.js,将我们的业务代码与阿里云函数计算的入口进行对接:

var getRawBody = require('raw-body');
module.exports.handler = function(req, resp, context) {
    let options = {
        themeTemplate: 'index.jade'
    };

    let aglio = require('aglio')
    getRawBody(req, function(err, body) {
        aglio.render(body.toString(), options, function (err, html, warnings) {
            if (err) return console.log(err);
            if (warnings) console.log(warnings);
            resp.send(html);
        });
    }); 

这里通过引入require('raw-body');来获取请求的 body,通过 Aglio 处理后返回。

之后执行fun deploy部署服务。注意:node_modules文件夹的内容也要一并上传,函数计算不会再次进行拉包。

魔改 Aglio

在阿里云函数计算的控制台中调试我们刚才部署的函数,发现会报 502 错误。
问题出在 Aglio 在渲染 markdown 时,会往node_modules目录下写入一个JavaScript的临时缓存文件。但阿里云的函数计算只开放了/tmp目录下的写入权限,其余都是只读。
那么这里我只能魔改 Aglio 源码了。还好函数计算不会使用包管理拉包,它就只用我们传上去的node_modules
问题出在 Aglio 的文件写入那里,我们只需更改写文件的目录即可:
/node_modules/aglio-theme-olio/lib/main.js文件,第 144 行与第 249 行:

// Line 144
//compiledPath = path.join(ROOT, 'cache', (sha1(key)) + ".css");
compiledPath = path.join('/tmp', (sha1(key)) + ".css");

// Line 249
//compiledPath = path.join(ROOT, 'cache', (sha1(key)) + ".js");
compiledPath = path.join('/tmp', (sha1(key)) + ".js");

然后写入的 JavaScript 的临时文件中,有使用require引入node_modules目录其它的包,这里的相对路径我们改成绝对路径,否则还是会报错 502。
还是在main.js文件下,第 236 行:

// Line 236
//return compiled = "var jade = require('jade/runtime');\n" + (jade.compileFileClient(filename, options)) + "\nmodule.exports = compiledFunc;";
return compiled = "var jade = require('/code/node_modules/jade/runtime');\n" + (jade.compileFileClient(filename, options)) + "\nmodule.exports = compiledFunc;";

之后再部署,就可以看到啦~

总结一下吧~

又学到了新的玩意儿呢。对于一些功能单调、而又十分常用的功能,又不想专门放在服务器上花心思去维护,不妨可以尝试一下阿里云的函数计算。Serverless 这个东西,用得好真的可以解决很多问题。
阿里云的fun工具很好用,让我能快速部署从而能进行调试。这一次下来也踩了很多坑,感觉阿里云的这个仅/tmp目录可写的设定就很蠢。他为何不能改成当前代码执行目录可写呢?然后 Aglio 方面,Aglio 可以说是 API Blueprint 目前可定制度最高的工具了,这点不可否认。像临时缓存文件目录写死在node_modules,这个从开发的角度其实也能理解啦。我一开始也不相信自己能魔改成功的哈哈。

然后关于函数计算的定价方面
这个真的不用太担心,阿里云财大气粗。
函数计算-定价

每月免费次数 100 万次!!
128Mb 每月免费秒数:3200000秒!!换算一下大概是 37 天。也就是说我即使一个月内一秒一次地调用都够。
因此对于个人用户来说,函数计算真的是完全免费了。

这里需要注意一下阿里云内存的计算方式,他并不是按照函数运行时的实际内存占用计算的,而是按照你给函数运行环境设定的执行内存计算。
也就是说我设定 1024 Mb 的最大执行内存,即使实际调用时远远没有用到这么多,阿里云还是按照 1024 Mb 来计费。
推荐是设定实际运行内存占用的两倍大小。像我这个 markdown 渲染,一次实际占用内存 66 Mb 左右,因此我选择的是 128 Mb 的执行内存。

接下来要做的就是关掉函数计算的公网访问,然后让 ECS 从内网调用它。如果可以的话,再把函数计算的日志给打开,后面还要继续探索。(≧∇≦)ノ

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
17天前
|
人工智能 Java Serverless
阿里云函数计算助力AI大模型快速部署
随着人工智能技术的快速发展,AI大模型已经成为企业数字化转型的重要工具。然而,对于许多业务人员、开发者以及企业来说,探索和利用AI大模型仍然面临诸多挑战。业务人员可能缺乏编程技能,难以快速上手AI模型;开发者可能受限于GPU资源,无法高效构建和部署AI应用;企业则希望简化技术门槛,以更低的成本和更高的效率利用AI大模型。
77 12
|
3月前
|
人工智能 自然语言处理 Serverless
阿里云函数计算 x NVIDIA 加速企业 AI 应用落地
阿里云函数计算与 NVIDIA TensorRT/TensorRT-LLM 展开合作,通过结合阿里云的无缝计算体验和 NVIDIA 的高性能推理库,开发者能够以更低的成本、更高的效率完成复杂的 AI 任务,加速技术落地和应用创新。
179 13
|
2天前
|
人工智能 JSON Linux
利用阿里云GPU加速服务器实现pdf转换为markdown格式
随着AI模型的发展,GPU需求日益增长,尤其是个人学习和研究。直接购置硬件成本高且更新快,建议选择阿里云等提供的GPU加速型服务器。
利用阿里云GPU加速服务器实现pdf转换为markdown格式
|
3月前
|
存储 人工智能 运维
正式收官!阿里云函数计算携手优酷,用 AI 重塑影视 IP 创新边界
近日,阿里云联合优酷发起的 Create@影视 IP x AI 应用创新大赛,将网剧《少年白马醉春风》这一热门影视 IP 与阿里云 AI 技术相结合,由阿里云函数计算提供 AIGC 技术支持参赛者基于网剧《少年白马醉春风》IP 或“少年江湖”精神内核,用 AI 生成角色场景设计、手办设计、破次元合照、数字人等多样化的作品。
135 10
|
9天前
|
弹性计算 Cloud Native Serverless
阿里云 SAE 邀您参加 Serverless 高可用架构挑战赛,赢取精美礼品
阿里云 SAE 邀您参加 Serverless 高可用架构挑战赛,赢取精美礼品。
|
2月前
|
人工智能 弹性计算 运维
触手可及:阿里云函数计算助力AI大模型的评测
阿里云推出的面向AI服务器的功能计算(Functional Computing, FC),专为AI应用提供弹性计算资源。该服务支持无服务器部署、自动资源管理和多语言支持,极大简化了AI应用的开发和维护。本文全面评测了FC for AI Server的功能特性、使用体验和成本效益,展示了其在高效部署、成本控制和安全性方面的优势,并通过具体应用案例和改进建议,展望了其未来发展方向。
189 4
|
3月前
|
SQL 分布式计算 Serverless
阿里云 EMR Serverless Spark 版正式开启商业化
阿里云 EMR Serverless Spark 版正式开启商业化,内置 Fusion Engine,100% 兼容开源 Spark 编程接口,相比于开源 Spark 性能提升300%;提供 Notebook 及 SQL 开发、调试、发布、调度、监控诊断等一站式数据开发体验!
173 3
阿里云 EMR Serverless Spark 版正式开启商业化
|
3月前
|
Cloud Native 关系型数据库 Serverless
基于阿里云函数计算(FC)x 云原生 API 网关构建生产级别 LLM Chat 应用方案最佳实践
本文带大家了解一下如何使用阿里云Serverless计算产品函数计算构建生产级别的LLM Chat应用。该最佳实践会指导大家基于开源WebChat组件LobeChat和阿里云函数计算(FC)构建企业生产级别LLM Chat应用。实现同一个WebChat中既可以支持自定义的Agent,也支持基于Ollama部署的开源模型场景。
691 28
|
3月前
|
人工智能 运维 大数据
阿里云“触手可及,函数计算玩转 AI 大模型”解决方案评测报告
阿里云“触手可及,函数计算玩转 AI 大模型”解决方案评测报告
118 2
|
4月前
|
存储 运维 安全
函数计算产品使用问题之如何获取到访问其他阿里云服务所需的AccessKey、SecretKey或STS Token
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。