整道题目的问题是设计一个CDN,负责按照给定的uri向registry请求tar文件,然后按照相对应的请求模式来给出相应的响应模式。程序整体的设计是一个多线程的预生成线程池,main(master)线程占用listenfd来监听所有链接请求,worker线程们通过P-V响应来从一个循环buffer中获取connfd与客户端通信。即Producer-Consumer模型。
在每个worker中,获取到connfd后会调用一个统一的服务器服务函数,来完成完整的请求-响应逻辑。
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install libarchive-dev- 如何从registry上请求代码包?
- 如何解压tar文件?
- 怎么编写可靠的parse函数来解析不同形式的请求uri,向接下来的步骤传递正确的uri
- 为什么返回的错误码与预期的不同?如何通过安装CA来解决问题?
- 由于没能及时更新引用变量的所有地方而引起的各种小错误...
第一眼读到byrarchive的题面时多少已经大致有了概念。从9月12日开始学习CSAPP,刚好在昨晚看到预生成并发部分。于是程序的大致框架就是用预生成的多线程池应用PC模型来进行多并发的实现。于是刚动手的第一件事就是完成了并发操作部分和循环buffer的构建,写出了PC模型需要用到的相关库依赖。
接下来需要想方设法解析多种不同的uri。题目中给出了不同的uri示例:
| URI | 含义 |
|---|---|
| /package@version/ | 解析到package的指定version |
| /package(@version)/filepath | 解析到package(可指定version)的具体文件 |
| /package/ | 解析到package的最新版本 |
| /package@^version/ 或 /package@~version/ | 解析到高于^version的最新版本 或 指定版本范围 |
| /package@beta/package.json | 解析到dist-tags对应的版本 |
如何解析参见具体实现
解析了uri之后我们就要构建请求,向registry请求package.json,这里涉及到两步操作:
- 构建uri
- 读取package的json操作
得到正确的uri就只需要从registry下载package.json的内容了。为了减少重复访问的次数,程序会在本地按照一定的命名规则对每个第一次下载的包创建一个对应的文件夹来命名存储。如何便捷访问package.json的内容呢
查阅CSDN,得知在C中有个cJSON库,能够便捷地实现对json文件的操作,且比手动解析更具有可靠性。在package.json中记录着所有需要的入口文件等的定义。根据npm生态的惯例:
| package.json | 入口文件 |
|---|---|
| exports["."] -> 对象 | 取default字段 |
| exports["."] -> 字符串 | 取路径 |
| 没有定义exports["."] | 使用main字段 |
| 以上两者都没有 | 退回到index.js |
得到了正确的入口文件内容后,现需要判断本地缓存是否有请求的库,如果有,则可以直接返回响应的内容。但没有的话,就需要下载tar文件并进行解包。和之前请求package一样,请求tarball用到的也是curl库,它能创建一个会话,根据指定的设置来和registry通信,将包下载到本地。使用membuffer来管理所有分块传输的数据,在回调函数write_cb中被更改,并将所有数据存储在自己的data中。
最后一步就是判断请求内容(mime),以及按照正确的内容返回正确的文件/目录了。使用了两个函数对应两种不同的情况:文件/目录。
整份代码让我比较心仪的地方是有严谨的数据管理格式,Requested_t 和 ParsedUri_t将每一部分所需要用到的相关数据方便地组织在一起,提高了代码的简洁性。这是我在之前的编程中很少实现过的。
| 优点 | 缺点 |
|---|---|
| 能够实现scoped包的版本解析功能 | 解析逻辑仅支持x.y.z格式,对>1.0.1或x-beta.y这样的格式缺乏支持 |
| 使用sbuf作为共享缓冲区,实现多线程P-C模型 | 对极大文件或海量小文件的传输缺少测试 |
| 代码组织模块化 | file_doit和target_filepath的路径构造多次出现 |
| 使用./tmp作为持久化缓存,优化性能 |
Gemini-2.5-pro:帮助我在写代码的时候找到思路,提供关键灵感,包括如何解包tar文件,怎样增强路径安全问题和拓展题目中的解析路径方面进行提示。代码中有ai风格的注释就是Gemini生成代码的时候写的,应该在检查安全路径那里可以看到有明显不同。
在测试过程中,Gemini还能够根据我反馈的错误信息在代码中定位可能的错误地点,为debug提供了非常方便快捷的帮助。
Change 0923:
- 用Gemini写了个home.html,提供默认的网站支持,做的网页相当美观,挺中意的
- 更新了新的对入口文件的解析规则
