⌈产品⌋ 网站开发、上线维护与用户运营全流程记 x 墨灵音乐

(。•ˇˇ•。)我没能给墨灵过上 4 岁生日。
关闭之际,我想回顾这近 1300 天的历程。
墨灵是 mkplayer 开源项目的改进版,也是我作为计算机初学者的第一个练手的项目。诞生之际,我没想过会有这么多人会去用它。
随着墨灵的长大,它的经历越来越丰富,故事越来越多。

技术

前端

JS

当时只学会了最基本的 JS,还没接触 Vue 等。没有使用 ES6,因为浏览器兼容(vivo 手机浏览器…)问题。

没用上 Worker 、PWA 那些玩意。使用各种小玩意来优化前端性能。不得不叹息一句:WebSQL 普及的真差。

总有人问我,前端 JS 为什么加密?前端加密一定是可解的。接口不希望轻易暴露,加密也只防君子不防小人。事实证明:It worked.

CSS

大量使用动画,使用完善的 WEUI 库来支持夜间模式。是从 WEUI 库的源码中学会如何只使用 CSS 来完成夜间和白天的主题切换。
alt text
alt text

异常上报

使用 Sentry、frontjs 平台监控。主要用来防止更新版本后 bug 爆发。

埋点统计

依次使用了百度统计、Google Analysis、自建程序,最后回到了百度统计。因为埋点过多,自部署的开源埋点无法处理大量的数据导致服务器屡次阵亡,最后放弃。百度统计比谷歌统计更加清晰;谷歌统计非常细化,只适用于商业化站点。

www.frontjs.com


后端

PHP

至今还在疑惑 PHP 为何会 503。现在能说得通是肉鸡扫服务器时提交了垃圾数据,程序没有做异常处理,然后。

无数据库:因为不需要。程序的缓存和大量小文件数据都存放在高效的文件系统中。

唯一遇到的问题就是数据迁移与备份。硬盘中存储了超过 900 万的缓存。初期未预知到文件这么多,导致硬盘 inode 爆满。

alt text

部署

服务器

为了控制成本(穷),各种优惠服务器真是能嫖就嫖。主站、API、鉴权分别部署在三台主机上,这些服务器高性能高 IO,稳定可靠。下载服务器部署在若干主机上,这些服务器低性能、高带宽高存储。

前后大大小小的服务器部署了至少有 50 台。牢记:快照、先备份再操作。

域名

域名前后换了几个。还是 COM 最香。

DNS

用的 DNSPOD 企业基础版,主要用到的是负载均衡功能。下载独立使用一个域名,根据主机权重在 DNS 层面实现负载均衡。这样最简单,但显然这样的负载均衡不是严格按照权重分配的。

CDN

用的腾讯云全球 CDN。特殊时期: CLoudflare Pro 版本。阿里 CDN 功能过于细分,不适合。腾讯云 CDN 无攻击减免,下图为被攻击惨况。

alt text

运行状态

主机监控使用的是阿里云云监控,用于监控全部主机的 CPU 等核心信息;
alt text

外部监控使用的是 UptimeRobot PRO(一个国外的平台),用于监控域名、主机、CDN 的外部可通性和可用性。

alt text

攻击

这三年,很荣幸体会到 DNS FLOOD 攻击、云服务器 DDOS 攻击、CDN DDOS 攻击、API 接口伪造攻击。没有很好的对付策略,放平心态。用 PHP 写了一套自己的 IP 评分机制,用来阻止 API 接口攻击。
alt text
alt text

其他

域名多次被腾讯封锁,猜测是被别人恶意举报,被网友们提交申诉救回来了。是个奇迹,我自己没想到能起死回生。

因为兼容性强,用上了付费 SSL 证书。为国内环境开启了 OCSP。

版本控制

没用上 Git 来实现版本控制,无法追溯 bug 让人头痛。

一些数据

持续运行了 1300 天左右;每天播放约 70 万首歌曲(不去重);每天平均搜索过 13 万次(不去重);用户群创建了 12 个,后面建不动群了,干脆就把整个群清空再加人;代码除去库,标准格式化后估摸 1 万行,感觉没啥意义。

总结

值得被吐槽的地方很多,当时的我还要兼顾高考,只能做到这水平了。
如果有机会,肯定会用上最新更适合的技术来写。

每个部分实现起来并不复杂。然鹅,完整地跑起来并让它持续地跑是一件相当有挑战的事情。一个人顾及方方面面,确实不易。因为平时很忙,所以断断续续地在维护。维护的不连续性也产生了很多麻烦。

现在回看,我觉得最糟糕的是:很多东西没有深入理解或者学习,就用上了。比如 :SSL 原理不懂,就给部署上了。JS、CSS 没系统学,边写边抄。

下一次的目标

或许有一天我会“卷土重来”。始终维护旧项目,会让自己的技术落后,一直困在舒适圈里面。至始至终,代码是一个人在写。所以,都是自己想怎么来就怎么来。如果有那么一天,我会进行重构。模块化、组件化、规范化,是下一次的目标。有感于文章


非技术总结

刚部署之时

起初,我只是当作一个练手程序去做。所以,我的绝大多数时间都是用在“写新功能”(自娱自乐)上。那个时候,更新墨灵是一件非常简单的事情:写代码 → 推送到服务器 → 完成。

小有名气之时

当墨灵的用户越来越多的时候,问题随之暴露。

  1. 第一个阶段添加的新功能,未做浏览器兼容测试,未做细节优化,功能只是处于能用的阶段。一个好的程序的功能应该是“易用的”,而不是“能用的”。随着用户提交的反馈越来越多,墨灵开始细化功能,打磨用户的每一次点击。
  2. 我发现我也不能再像之前一样更新墨灵,因为我的一次隐藏着 bug 的更新会波及到非常多的用户。所以,更新墨灵变成了一件富有挑战的事情:收集用户反馈、确定要更新的内容 → 编写代码 → 本地多次测试 → 凌晨推送更新 → 线上测试 → 决定是否回滚代码 → 完成。 挺累,但挺好。

初具规模

(╯‵□′)╯︵┴─┴ 当墨灵的用户再翻倍的时候,问题又来了。

  1. 服务器“爆炸”了。服务器其实没有那么神秘,它和你家的电脑、手机没有本质区别。服务器爆炸意味着服务器太忙了,也意味着该加钱了。
  2. 费用“爆炸”了。买服务器要钱,钱包受伤。
  3. 我“爆炸”了。服务器满载,我挺开心的,自己的东西能被人用,谁不开心呢?然而,我发现了不善的访客,他们在恶意消耗服务器资源。墨灵一直没有做登录功能,不是我不能,是我不想。对于用户而言,登录是一种麻烦。对于我而言,登录功能意味着把用户进行分类,或者说我可以选择差异对待用户。这不是墨灵的初衷。因此,每一个用户对于我们来说都是匿名访问。然而,这种“匿名”给我们带来了麻烦,不足 0.1% 的恶意用户消耗着我们 80% 的资源。我花了大量的时间,在尽量避免影响正常用户,不加入登录功能的情况下,去解决这个问题。值得开心的是,这个问题被解决了。遗憾的是,我投入了大量的精力以至于拖延了整体更新进度;会影响极少数网络环境异常但确实是正常用户的访问。我写了这么长的一段来说这个问题,是有原因的:不仅仅是我,任何网站的开发者,在用户量上升的阶段一定会遇到这个问题。开发者们都非常头痛,用户的不理解往往加剧了这个问题。

墨灵教会我的,也是最重要的:一个程序的功能完整是基础,最最最重要的是功能易用。功能上线前的一次次测试,是为了提高功能的易用性。一个程序的某个功能不能正常运作,不应该是告诉用户“开发者预期的操作过程”,而是程序本身应该足够完善,无论用户做了什么动作,用户都能得到它预期的结果。这就好像,一个好的产品,不需要说明书,无论是傻瓜还是精通的人,无论是老人还是年轻人,都能轻易上手。条条大路通罗马,应该是一个程序设计的准则。当然,这也是墨灵每一次测试的准则。

感谢曾今用过墨灵,还看完这封信的你,你们对我的肯定是墨灵走下来的动力。

感谢陪墨灵一路走来的伙伴们,感谢你们愿意为我分担琐事,与我一同体验欢乐。

感谢曾今攻击过我们,滥用我们服务的伙计们,你们让我感受到我技术的不足,促使我提升自己。最初攻击的乐趣你们收获了,最后攻击打不过防御策略的无奈你们也收获了。