05|get hands dirty:做一个图片服务器有多难?
该思维导图由 AI 生成,仅供参考
Thumbor
- 深入了解
- 翻译
- 解释
- 总结
使用Rust语言构建图片服务器的思路和方法 本文介绍了使用Rust语言构建一个类似图片服务器的项目,以Thumbor图片服务器为例,展示了如何设计一个易用、简洁的接口来实现图片的动态转换。作者首先分析了图片转换服务的难点,提出了使用列表来表述图片处理的有序操作,并使用protobuf来描述数据结构,以实现可扩展的图片处理参数。接着讨论了如何在HTTP服务器中处理路由,以及如何提供LRU缓存来优化原始图片的获取过程。文章还介绍了使用Rust语言构建图片服务器的思路和方法,以Thumbor图片服务器为例,展示了如何设计一个易用、简洁的接口来实现图片的动态转换。通过分析图片转换服务的难点,提出了使用列表来表述图片处理的有序操作,并使用protobuf来描述数据结构,以实现可扩展的图片处理参数。同时,讨论了在HTTP服务器中处理路由,以及提供LRU缓存来优化原始图片的获取过程。文章鼓励读者用Rust语言构建这个工具,并期望用大约200行代码实现需求。整体而言,本文以实际项目为例,展示了使用Rust语言构建图片服务器的思路和方法,为读者提供了一种新的技术实践思路。文章还介绍了使用Rust语言构建图片服务器的思路和方法,以Thumbor图片服务器为例,展示了如何设计一个易用、简洁的接口来实现图片的动态转换。
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
全部留言(77)
- 最新
- 精选
- 大汉十三将置顶这一章学了 3 天, 终于能看懂一点了 : - 1.2: 开始接触, 一脸懵逼, 所有的代码个顶个的都看不懂, 极其痛苦的 1 个半小时 - 1.3: 通过强制自己问 chatgpt: xx 这段代码是干什么用的, 强制自己去熟悉 rust 的相关 library, 终于看懂了一些文件的一部分代码 2 h - 1.4: 基本把不会的都询问 Chatgpt 整理了一遍, 逻辑上都顺了, 剩下一些小的语法问题需要继续记笔记 1.5 h
编辑回复: 棒,get hands dirty 系列很多同学刚看都说很难看不懂,你是第一个把自己的学习过程贴上来的,给你置顶啦,学习思路正好也可以供其他同学参考~
2023-01-04归属地:北京27 - 葡萄看老师的项目,语言已经不是最重要的了。思路和组织结构真是赏心悦目。
作者回复: 谢谢赏识。我希望这门课不光能教会大家语言本身,更重要的是如何用语言提供的能力优雅地解决实际问题。有的人能用 C 写出面向对象的代码;有的人能用 Java 写出 Fortran 的感觉。Rust 为我们提供了强大的抽象能力,我们要用好它。:)
2021-09-01255 - pedro最让人无法接受的点: ```shell du -h -d 1 ./target 395M ./target/rls 901M ./target/debug 1.3G ./target ```
作者回复: 如果你觉得每个项目都有个 target,项目多了不好清理,那么可以编辑 ~/.cargo/config,让所有项目的编译结果都放在同一个目录下(不过这样无法同时编译多个项目,cargo 有文件锁): ``` [build] target-dir = "/Users/tchen/.target" ``` 如果你觉得编译后的结果太大,倒也不用担心,release build 比较小,目前 9M,这里还可以用很多方法进一步优化: ``` ❯ ls -l ~/.target/release/thumbor -rwxr-xr-x 2 tchen staff 9562656 Aug 30 12:09 /Users/tchen/.target/release/thumbor* ``` 至于如果你觉得编译的中间文件太大,nodejs 的 node_modules,python 的 virtualenv,都是吃磁盘的主。:)
2021-09-01321 - wzx为什么在main.rs中并没有见到引入: use tracing_subscriber; use reqwest; 却可以直接使用?
作者回复: reqwest 和 tracing_subscriber 已经是顶级 namespace,如果你想直接使用 get,你可以 use reqwest::get,但你如果就是要通过 crate 名引入其功能,可以直接使用,就跟我们可以直接用 std::sync::Arc 一样。Rust 下只要你加了依赖,对应的依赖就可以访问了,不存在 import 的过程。use 只是简化 namespace。
2021-09-0220 - Christian感概什么时候才能达到老师这样的高度?
作者回复: 苦干,实干,巧干。让勤勉追上时间的脚步。:)
2021-09-0116 - Fan逻辑清晰,喜欢这种教学方式。从项目,问题入手,也不是纠结于语法细节。
作者回复: 👍
2021-09-0114 - MichaelRust,相比起有运行时Go语言,运行效率不再话下。另外,作为现代系统级编程语言,在工程实践,依赖管理,相比起C、C++要好很多,但是比起Go稍微复杂一些。 语言学习难度还是挺大的,很多新概念,新名词都要理解,不过写起来还是挺爽的。用半年实践反复学习实践,希望能啃下这门语言。 希望老师从先行者的角度,对一些难点,易错点,平时不容易接触的到的地方给学生们做下讲解,看书和看网上资料千篇一律,没什么新奇的地方,大多讲的不够透。
作者回复: 嗯,会的,后续的文章我们紧扣数据结构在栈和堆上的关系展开,我觉得这很重要,但似乎没有人这样讲解。接下来的课程你会慢慢看到的。
2021-09-038 - Quincy请问老师还有什么新的图片引擎吗?可以推荐一个吗?在 github 和 crates.io 上没有找到相似的,谢谢老师
作者回复: 几个选择: - 你可以直接在 image 库上实现 - 使用 imagemagick: https://github.com/nlfiedler/magick-rust - 使用 opencv: https://github.com/twistedfall/opencv-rust - 使用 piet: https://github.com/linebender/piet - 或者任何 C/C++ image 库(需要做一下 rust binding)
2021-09-0128 - Quincy添加新功能: 1. 首先添加新的 proto ```proto message PaddingBottom { uint32 x = 1; } // 一个 spec 可以包含上述的处理方式之一 message Spec { oneof data { ... Watermark watermark = 7; // 处理水印 PaddingBottom paddingBottom = 8; // 填充图片 } } ``` 2. 定义新的 spec然后为 spec 实现 SpecTransform trait 和一些辅助函数 ```rust // File: 在文件 `pb/mod.rs` 中 // 提供一些辅助函数,让创建一个 spec 的过程简单一些 impl Spec { ... pub fn new_padding_bottom(x: u32) -> Self { Self { data: Some(spec::Data::PaddingBottom(PaddingBottom { x })) } } } ``` 3. 最后在 Engine 中使用 spec ```rust impl Engine for Photon { fn apply(&mut self, specs: &[Spec]) { for spec in specs.iter() { match spec.data { Some(spec::Data::Crop(ref v)) => self.transform(v), ... Some(spec::Data::PaddingBottom(ref v)) => self.transform(v), _ => {} ... impl SpecTransform<&PaddingBottom> for Photon { fn transform(&mut self, op: &PaddingBottom) { let rgba = Rgba::new(255_u8, 255_u8, 255_u8, 255_u8); let img = transform::padding_bottom(&mut self.0, op.x, rgba); self.0 = img; } } ``` 4. 在 main.rs 函数中使用 ```rust // 调试辅助函数 fn print_test_url(url: &str) { use std::borrow::Borrow; let spec1 = Spec::new_resize(500, 800, resize::SampleFilter::CatmullRow); let spec2 = Spec::new_watermark(20, 20); let spec3 = Spec::new_padding_bottom(100); // new let spec4 = Spec::new_filter(filter::Filter::Marine); let image_spec = ImageSpec::new(vec![spec1, spec2, spec3, spec4]); let s: String = image_spec.borrow().into(); let test_image = percent_encode(url.as_bytes(), NON_ALPHANUMERIC).to_string(); println!("test url: http://localhost:3000/image/{}/{}", s, test_image); } ```
作者回复: Wow,你是第一个把思考题答案贴出来的!看得出理解了代码,并且还研究了一下 photon_rs 的能力。非常棒!
2021-09-0128 - 茶底逻辑清晰,泪目了,我咋就这么菜
编辑回复: 哈哈大佬也是坚持不懈学出来的,看到差距就已经看到学习方向了,加油💪
2021-09-016