Bearweb网站架构-简介
Bearweb是一个为个人网站与小型组织设计的轻量级的数据库驱动PHP网站架构。Bearweb使用简单的数据库与代码结构,致力于降低网站维护难度与成本。
Bearweb, Website, 网站, Framework, 架构, Database-driver, 数据库驱动, Web dev, 网站开发
--by Captdam @ Jul 2, 2023Bearweb是一个为个人网站与小型组织设计的轻量级的数据库驱动PHP网站架构。Bearweb使用简单的数据库与代码结构,致力于降低网站维护难度与成本。
这个页面简单介绍一下Bearweb的特点与开发过程。
开发初衷
最早是本科大一的时候一个MC游戏群决定搞一个网站,顺便也想给高中社团做一个宣传网站。当时用过不少架构,比如Discuz,比如Moodle,后来给别人做东西还用过Wix,但是都不太符合我所需要的功能需求。当时Wordpress还不是很出名,不过即使尝试过Wordpress估计现在也不会用。对于Discuz,当时想的是论坛架构即可以公开展示,也可以设置必须要注册登录的内部讨论模块;但是,Discuz的代码结构与数据库非常繁杂,十分难维护与数据迁移。Moodle是给课堂开发的,我高中物理老师使用哪个架构,所以我也进行了尝试;但是Moodle对于系统资源的占用似乎很大,总是崩溃。至于Wix,讲个笑话,我的网站我甚至都没办法拿到自己的数据。而Wordpress呢,用户很多,bug也很多,机器人也很多。
后来在2017年,终于决定自己造轮子开发Bearweb作为我的个人博客与社团网站的底层架构。因此,这个架构再设计与开发时就主要考虑个人与小型组织网站对功能与维护成本的需求。Bearweb现在已经过数次迭代,每一次迭代我都尝试加入一些新功能,删除一些不常用的功能,简化代码结构,降低模组之间耦合度。
最早开发时还是看着各种教学网站照葫芦画瓢,PHP代码与HTML代码混搭(虽然现在也有),表单提交的页面和返回结果的页面写在一个脚本里面,可以由本地JS脚本处理的美观类的任务在服务器上面处理,甚至网站主页排版使用了一个巨大的table而且没有写CSS。不过,在不断学习与试验中,也慢慢将以前的代码修改得更简便更高效了。
虽然现在也看到了不少可以生成静态化网站host在Github上面的系统,感觉也不错。不过,既然开发都做了这么久了,那就继续做下去吧,也算是不断学习与思考的一个经历。以后和人吹牛还能说自己也做过全栈:P。
Bearweb特点
简化代码与数据库结构
最早决定自己造轮子就是因为现成的架构的代码结构与数据库结构非常繁杂。架构设计有一句老话“Simplicity favors regularity”,简单的设计能够让代码更高效,更便于维护。
Bearweb的代码分为两部分:核心模组与处理模板:
核心模组只负责读写元数据并为处理模板提供基础的接口。几大核心模组都拥有自己独立的数据库,代码相互独立,只是用定义好的接口交流极少的数据。当一个模组出错,Bearweb将会使用一个安全的默认值,并且其他模组将不会被影响。
处理模板负责将元数据与前端数据的转换。不同页面的不同功能由完全独立的处理模板负责,不同的处理模板是完全不相关的。
Bearweb处理请求的流程也非常简单。所有的请求都使用这样的处理模式:请求首先由核心模组进行处理,进行数据库的读写,并将元数据提供给处理结构。处理模板将元素据按照需求转化为前端的数据并返回给客户端。如果客户端有提交数据(API模板),处理模板会将处理好的用户数据返回给核心模板,并由核心模板写入数据库。对于非常不常用的功能,处理模板将会按照定义好的规定直接读写数据库(为了保持核心模板的简化)。
数据库的结构也非常简单,没有外键,完全可以手动维护。在编写Bearweb时也考虑到了数据库可能会被手动维护,因此加入了对数据库出错的对策。
使用SQLite
在代码中,Bearweb使用PDO操作SQLite数据库。当前版本的Bearweb代码是在不同核心模组使用独立的SQLite数据库为基础上构建。理论上来说,Bearweb也可以使用其他数据库,例如之前版本的的Bearweb就使用mySQL,但是一些使用SQLite特性的非标准SQL语言需要进行修改(例如INSERT INTO table (a,b,c) VALUES (?,?,?) RETURNING *
)。
相较于其他DBMS,SQLite没有独立的服务,而是由PHP脚本使用SQLite库直接读写数据库文件。因此,使用Bearweb不需要额外安装数据库服务器,只要由文件读写权限,就可以成功运行。
因为SQLite的每个数据库都是一个文件,写数据库操作将会暂时锁数据库文件。为了提高处理的并行性,Bearweb的每个核心模组都是用独立的数据库以降低等待其他线程完成写数据库的等待。因为不同模组使用的数据库是完全独立的,因此没有办法建立外键,所以Bearweb在设计上要求模组之间去耦核性。
虽然SQLite支持同一数据库内的transaction,在设计上,Bearweb避免使用begin/rollback/commit的设计以降低代码的复杂度。Bearweb使用将多个操作放在同一条query内的方式达到原子性。
半静态
为了降低服务器的系统负载,Bearweb将部分操作静态化。
在架构上来说,Bearweb需要通过请求的URL从数据库中读取资源,并根据客户端提供的用户信息判断用户是否由读写资源的权限。因此,在基础架构上,Bearweb只能是动态的。
对于资源的数据,Bearweb在数据库中保存只需要非常少处理就能返回给客户端的数据。例如对于一个网页,Sitemap
数据库中Content
值就是该网页的HTML代码;对于一张图片,Sitemap
数据库中Content
值就是该图片的二进制数据。而不是保存网页的markdown或是图片的base64这种需要处理后才能发送的数据。
对于列表类型的页面(例如sitemap.xml),Bearweb使用两种策略:
在请求该页面后,Bearweb会将生成的列表缓存下来,并设置一个过期时间。在过期前,每一次请求这个页面都只会读取这个缓存下来的页面。当然,修改任何会被这个列表包含的资源后,也可以重新生成列表而不是等到该列表过期后才更新。
修改任何会被这个列表包含的资源后,就重新生成列表。当然,也可以定时强制让这个列表更行,防止出现错误。