今天心血来潮,介绍一下我的新博客站点 —— https://EWhisper.cn。
我是做基础平台 PaaS 运维和架构的,挺喜欢把工作中学到的新知识写下来、记笔记,突然有一天就抱着「资源共享、天下为公」的理念,分享我的学习心得,也能让我的文章更规范刻度。
我是从 2019 年开始折腾博客的,然后在 2021 年对博客进行了一下全新的改版,在最新版的博客中,无论是使用还是部署,都采用采用了 JamStack 的技术架构和工具。目前来看效果也不错。
{% note light %}
?问题:
第一代网站,目前还在这里留了个底 —— https://www.EWhisper.cn 由 Pelican 静态站点生成器,NGINX Web Server,Docker ,腾讯云 云主机提供支持。主题目前来自Smashing Magazine。
效果如下图所示:

{% note info %}
?参考资料:
Pelican 是一个用 Python 编写的静态站点生成器。亮点包括:
第二代网站 —— https://EWhisper.cn 由 Hexo 静态站点生成器,七牛云-对象存储和CDN 提供图片存储和URL,腾讯云 CloudBase-静态网站托管 提供静态网站托管支持,valine 或 Twikoo 提供评论系统技术支持,博客访问量和评论信息存储在 LeanCloud 或 腾讯云 CloudBase-用户管理上,统计分析通过百度统计 和 LeanCloud 来实现,博客首页动态诗词展示由一言开发者中心接口提供。主题目前来自 hexo-theme-fluid。
效果如下图所示:

下面一一介绍。
{% note info %}
?参考资料:
Jamstack 架构中的 JAM 是指客户端 JavaScript、可重用的后端 API,和用户界面的 Markup,比如 HTML 与 CSS。
Jamstack 的关键特征是前端 Web UI 与基于 API 的后端服务之间的清晰区分。与垂直集成的传统 Web 应用程序不同的是, Jamstack 应用程序是模块化和分散式的:UI 可以通过静态网页服务器、CDN、甚至基于区块链的存储进行分发;后端 API 服务可以部署在云上,也可以由边缘节点就近提供服务。
我们先说 JAM 架构
J 是指 客户端 JavaScript,那么我的博客中涉及到的 JavaScript 主要有以下:
JS 静态站点生成器框架:Hexo,我在自己电脑上用 Markdown 格式写文章,通过 hexo g 生成网站静态页面,并通过 hexo deploy 进行部署。
部署托管:腾讯云 CloudBase,这里是使用了它的:
hexo deploy 一起工作,将网站文件发布到腾讯云上(静态部分具体使用了:DNSPod、COS 和 CDN)静态网站评论系统:Twikoo,这里使用了它的 JS 前端和基于腾讯云 CloudBase 的云函数后台。
网页访问统计:
百度统计效果如下:

LeanCloud 展示效果如下:


后端存储数据如下所示:

{% note info %}
?参考资料:
Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。Hexo 基于 JavaScript 和 Node.js。
腾讯云 CloudBase:云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等 serverless 化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
Twikoo:一个简洁、安全、免费的静态网站评论系统,基于腾讯云开发。部分特色如下:
效果如下:

LeanCloud:LeanCloud 本质上提供的服务和腾讯云的 CloudBase 是一致的。LeanCloud 领先的 Serverless 云服务,为产品开发提供强有力的后端支持。提供一站式后端服务,如数据存储、云引擎、即时通讯等。
A 指可重用的后端 API。其实 J 和 A 是紧密配合的,我们在上一段也能看到很多 JavaScript 最终都是调用 API 来对数据进行增删改查。我的博客中涉及到的 API 主要有:
如果大家访问我的网站——容器化应用系统上生产的最佳实践 - 东风微鸣技术博客 (ewhisper.cn),看评论,打开浏览器的 F12,就可以看到实际 Twikoo POST 的 API 是:
curl 'https://ewhisper-5g565139594f9b52.ap-shanghai.tcb-api.tencentcloudapi.com/web?env=ewhisper-5g565139594f9b52' \
-H 'authority: ewhisper-5g565139594f9b52.ap-shanghai.tcb-api.tencentcloudapi.com' \
-H 'sec-ch-ua: "Microsoft Edge";v="95", "Chromium";v="95", ";Not A Brand";v="99"' \
-H 'x-tcb-region: ap-shanghai' \
-H 'x-sdk-version: @cloudbase/js-sdk/1.7.0' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.38' \
-H 'content-type: application/json;charset=UTF-8' \
-H 'x-seqid: 04c3430d22965' \
-H 'x-tcb-trace: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiZWQ1OWE2MmFiYmIyNDZkY2JiNTRiODVjMzU5MGMxNTEiLCJsYXN0UmVwb3J0VGltZSI6MTYzNTY0NzI4MTI2OSwiaWF0IjoxNjM1NjQ3MjgxfQ.GiVnirzhrEf7AnNxV_QejyH9Tk7shmmVG6Xh5yiUPn0' \
-H 'sec-ch-ua-platform: "Windows"' \
-H 'accept: */*' \
-H 'origin: https://ewhisper.cn' \
-H 'sec-fetch-site: cross-site' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-dest: empty' \
-H 'referer: https://ewhisper.cn/' \
-H 'accept-language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7' \
--data-raw '{"action":"functions.invokeFunction","dataVersion":"2020-01-10","env":"ewhisper-5g565139594f9b52","function_name":"twikoo","request_data":"{\"event\":\"COMMENT_GET\",\"url\":\"/posts/14417/\"}","access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoie1wibG9naW5UeXBlXCI6XCJBTk9OWU1PVVNcIixcImVudk5hbWVcIjpcImV3aGlzcGVyLTVnNTY1MTM5NTk0ZjliNTJcIixcInV1aWRcIjpcImVkNTlhNjJhYmJiMjQ2ZGNiYjU0Yjg1YzM1OTBjMTUxXCJ9IiwiaWF0IjoxNjM1NjUwOTU4LCJleHAiOjE2MzU2NTQ1NTh9.8hDap2wwrTII2Ine8F9jjDzCGUKW_e80pb4KvpGM64U;1635566422","seqId":"04c3430d22965"}' \
--compressed
API 返回的响应是:
{
"requestId": "91765a8a-39fc-11ec-9ab1-b2a89f885dbc",
"data": {
"response_data": "{\"data\":[{\"id\":\"cd045e75610b657002fe22fb26922cc4\",\"nick\":\"凯西Casey\",\"avatar\":\"https://thirdqq.qlogo.cn/g?b=sdk&k=JtvoGTkW8mBlnXNSFnxcxg&s=140&t=1557419902\",\"mailMd5\":\"097b6659c25b25c1ad2d792c6d5a953e\",\"link\":\"\",\"comment\":\"<p>自动关联qq头像<img alt=\\\":bilibiliHotKey-20:\\\" src=\\\"https://twikoo-magic.oss-cn-hangzhou.aliyuncs.com/bilibiliHotKey/20.jpg\\\" class=\\\"tk-owo-emotion\\\"> </p>\\n\",\"os\":\"Android 11\",\"browser\":\"Miui 15.1.12\",\"master\":false,\"like\":0,\"liked\":false,\"replies\":[],\"ruser\":null,\"isSpam\":false,\"created\":1628136816139,\"updated\":1628136816139},{\"id\":\"cd045e75610b634002fc99751dbc207c\",\"nick\":\"小囧\",\"mailMd5\":\"27add2425f31777763528269b4060ec1\",\"link\":\"\",\"comment\":\"<p><img alt=\\\":bilibiliHotKey-24:\\\" src=\\\"https://twikoo-magic.oss-cn-hangzhou.aliyuncs.com/bilibiliHotKey/24.jpg\\\" class=\\\"tk-owo-emotion\\\"> </p>\\n\",\"os\":\"Android 11\",\"browser\":\"Miui 15.1.12\",\"master\":false,\"like\":1,\"liked\":false,\"replies\":[],\"ruser\":null,\"isSpam\":false,\"created\":1628136256345,\"updated\":1628136256345},{\"id\":\"610b366fcb9d18021c807485\",\"nick\":\"东风微鸣\",\"mailMd5\":\"7c743bc6ac83171e35a5aa8bd66cc1ea\",\"link\":\"https://EWhisper.cn\",\"comment\":\"<p><img class="vemoji" src="https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/alus/alus_blush.png" alt="alus_blush"><img class="vemoji" src="https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/bilibili/bb_sunglasses.png" alt="bb_sunglasses"><img class="vemoji" src="https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/qq/qq_confounded.gif" alt="qq_confounded"><img class="vemoji" src="https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/tieba/tieba_antic.png" alt="tieba_antic"><img class="vemoji" src="https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/tw-emoji/1f47d.png" alt="1f47d"><img class="vemoji" src="https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/weibo/weibo_cat_cry.png" alt="weibo_cat_cry"></p>\\n\",\"os\":\"Windows 10\",\"browser\":\"Microsoft Edge 92.0.902.62\",\"master\":false,\"like\":0,\"liked\":false,\"replies\":[],\"ruser\":null,\"created\":1628124783184,\"updated\":1628124783184}],\"more\":false,\"count\":3}"
}
}
实际内容就是:

百度统计太复杂,我也不太懂,URL 是:https://hm.baidu.com/hm.js 读者可以自行查看。
LeanCloud 统计 PV、UV 和具体文章阅读量的 API 分别为:
PV:
https://lrbbjugq.lc-cn-e1-shared.com/1.1/classes/Counter?where={"target"%3A"site-pv"}
响应内容为:
{
"results": [
{
"target": "site-pv",
"time": 1395,
"createdAt": "2021-07-10T07:40:59.569Z",
"updatedAt": "2021-10-31T03:30:15.933Z",
"objectId": "60e94f0b55ba67136bafb203"
}
]
}
UV:
https://lrbbjugq.lc-cn-e1-shared.com/1.1/classes/Counter?where={"target"%3A"site-uv"}
响应内容为:
{
"results": [
{
"target": "site-uv",
"time": 397,
"createdAt": "2021-07-10T07:40:54.146Z",
"updatedAt": "2021-10-31T02:15:31.349Z",
"objectId": "60e94f06d3c62b4544b9ff5d"
}
]
}
具体文章阅读数:以容器化应用系统上生产的最佳实践 - 东风微鸣技术博客 (ewhisper.cn)为例
https://lrbbjugq.lc-cn-e1-shared.com/1.1/classes/Counter?where={"target"%3A"%2Fposts%2F14417%2F"}
响应内容为:
{
"results": [
{
"target": "/posts/14417/",
"time": 28,
"createdAt": "2021-07-31T08:39:50.194Z",
"updatedAt": "2021-10-31T03:30:15.926Z",
"objectId": "61050c5697a09641df17407d"
}
]
}
大家如果进入我的首页,多刷新几次,会发现首页的 Slogan 会出现不同的古诗句。如下:

这个其实也是调用的 API,博客首页动态诗词展示由一言开发者中心接口提供。
{% note info %}
?参考资料:
一言是创建于 2016 年的项目,起初是用于个人目的。目前已经转为公益项目,由萌创团队运营,为大家提供服务。 所谓一言(ヒトコト),即一句话。这句话可以是传达了感动,可以是博人一笑,可以是发人深思。总之,一言,代表着言语的触动,灵魂的交流。
具体的调用 URL 为:https://v1.hitokoto.cn/?c=i。c=i 表示句子类型(c)为诗词(i)。
返回的响应为:
{
"id": 5545,
"uuid": "5d9def79-c283-4c4c-a9cb-f44ac8da26da",
"hitokoto": "采得百花成蜜后,为谁辛苦为谁甜。",
"type": "i",
"from": "蜂",
"from_who": "罗隐",
"creator": "a632079",
"creator_uid": 1044,
"reviewer": 1044,
"commit_from": "api",
"created_at": "1586266392",
"length": 16
}
M 指的是用户界面的 Markup,比如 HTML 与 CSS。
我的博客对比了多个 Hexo 受欢迎的主题,最终选择了 fluid 。以下是我使用过的主题和我的简单评价。
{% note info %}
?参考资料:
Fluid 是基于 Hexo 的一款 Material Design 风格的主题,以简约的设计帮助你专注于写作,由 Fluid-dev负责开发与维护。
主题 GitHub: https://github.com/fluid-dev/hexo-theme-fluid
预览网站:Fluid's blog,zkqiang's blog
大家可以浏览 Hello Fluid - Hexo Theme Fluid (fluid-dev.com) 来体验该主题的风格
首先,文章全部托管在 Git 上。在我的电脑上安装好相关依赖:Git、Node.js 、 VSCode(用作 Markdown 格式文章写作、终端 Terminal 和 Git 版本管理)、hexo-cli(Hexo 的命令行)、hexo-theme-fluid(fluid 主题)和 @cloudbase/cli(腾讯云 CloudBase CLI)。
其次,在终端执行 hexo new "新文章" 创建新的 markdown 文件,并用 VSCode 对其进行写作和编辑。
文章完成后,通过终端执行 hexo s 生成新的文章网页,并本地预览。
最后,通过 cloudbase framework deploy ... 发布到腾讯云上。
这里也详细说一下 cloudbase framework deploy ... 都做了些什么,具体如下:
CloudBase CLI 1.9.2
CloudBase Framework 1.8.16
______ __ __ ____
/ ____// /____ __ __ ____/ // __ ) ____ _ _____ ___
/ / / // __ \ / / / // __ // __ |/ __ `// ___// _ \
/ /___ / // /_/ // /_/ // /_/ // /_/ // /_/ /(__ )/ __/
\____//_/_\____/ \__,_/ \__,_//_____/ \__,_//____/ \___/ __
/ ____/_____ ____ _ ____ ___ ___ _ __ ____ _____ / /__
/ /_ / ___// __ `// __ `__ \ / _ \| | /| / // __ \ / ___// //_/
/ __/ / / / /_/ // / / / / // __/| |/ |/ // /_/ // / / ,<
/_/ /_/ \__,_//_/ /_/ /_/ \___/ |__/|__/ \____//_/ /_/|_|
CloudBase Framework info EnvId ewhisper-xxxxx # 作者备注:CloudBase 的环境 ID
CloudBase Framework info Region ap-shanghai # 作者备注:腾讯云区域
CloudBase Framework info Validate config file success.
CloudBase Framework info AppName ewhisper
CloudBase Framework info ? install plugins
CloudBase Framework info callHooks 'preDeploy' # 作者备注:部署前操作
CloudBase Framework info ? init: hexo... # 作者备注:init
CloudBase Framework info Website 插件会自动开启静态网页托管能力,需要当前环境为 [按量计费] 模式 # 作者备注:环境是按量计费的。
CloudBase Framework info Website 插件会部署应用资源到当前静态托管的 / 目录下
CloudBase Framework info ? build: hexo... # 作者备注:build,就是调用 `npx hexo generate`
CloudBase Framework info running 'npm install --prefer-offline --no-audit --progress=false'
...
CloudBase Framework info running 'npx hexo generate'
# 作者备注:以下是 Hexo Generate 日志
INFO Validating config
INFO Start processing
INFO [Fluid] 读取 _config.yml 中 theme_config 配置项覆盖配置
INFO Generate link [41870] for post [source/_posts/我的基于JamStack的新博客.md][ 我的基于JamStack的新博客 ]
INFO Generated: categories [[ '云计算' ]] for post [source/_posts/我的基于JamStack的新博客.md][ 我的基于JamStack的新博客 ]
...
INFO 292 files generated in 1.8 s
# 作者备注:以上是 Hexo Generate 日志
CloudBase Framework info ? compile: hexo... # 作者备注:静态网站没有编译过程
CloudBase Framework info callHooks 'postCompile'
正在部署[░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 100% 40.0 s
正在部署[░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 100% 45.1 s
CloudBase Framework info ? deploy: hexo... # 作者备注:部署到腾讯云,其实调用的就是腾讯云 COS 的上传 API
CloudBase Framework info ? 网站部署成功
CloudBase Framework info callHooks 'postDeploy' # 作者备注:部署后展示应用信息
CloudBase Framework info ? 应用入口信息:
? 网站入口: https://ewhisper-xxx.tcloudbaseapp.com/
CloudBase Framework info ✨ done
其间,也会通过 Git 进行文章的版本管理和同步。
JAM 通用的用户访问路线如下所示:

Hexo 生产的站点,是完全的静态站点,全部都是静态文件,包括:HTML、CSS、JavaScript 和图片。这些静态文件,通过 cloudbase framework deploy ... 后,发布到腾讯云 CloudBase-静态网站托管。这里其实将静态文件发布到了 2 个腾讯云的产品中:
用户浏览网站时,过程如下:
对于 API 部分,需要开通、安装部署的主要有以下组件:
以上就是我的基于 JamStack 的博客 —— https://EWhisper.cn。主要是基于:Hexo、Fluid 主题、Twikoo 评论系统、LeanCloud 和 腾讯云 CloudBase 来实现的。
从我的角度来看,JamStack 相比传统 LNMP 开发,一些主要的区别包括:
总体而言,选择使用 Jamstack 创建网站有 4 个主要好处: 成本效益、性能改进、更好的安全性和更好的用户 / 开发者体验 。
欢迎体验!✨✨✨
三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我正在开发我的第一个Rubygem,并捆绑了cucumber、rspec和shoulda-matches进行测试。当我运行rspec时,出现以下错误:/app/my_gem/spec/spec_helper.rb:6:in`':undefinedmethod`configure'forShoulda::Matchers:Module(NoMethodError)这是我的gem规范:#my_gem.gemspec...Gem::Specification.newdo|spec|......spec.add_development_dependency"activemodel"spec.a
我正在使用Heroku(heroku.com)来部署我的Rails应用程序,并且正在构建一个iPhone客户端来与之交互。我的目的是将手机的唯一设备标识符作为HTTPheader传递给应用程序以进行身份验证。当我在本地测试时,我的header通过得很好,但在Heroku上它似乎去掉了我的自定义header。我用ruby脚本验证:url=URI.parse('http://#{myapp}.heroku.com/')#url=URI.parse('http://localhost:3000/')req=Net::HTTP::Post.new(url.path)#boguspara
require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame