【重要】涨潮了: 建立开放的模块化Web框架Tide
网络服务工作组今年的目标是改进网络开发:通过建立Tide(潮汐)框架,来改进基于async/await网络相关crate的生态系统。之所以取名为Tide(潮汐),意指“涨潮使得所有的船都得以上升”,也就是中国的那句成语,水涨船高。(开个玩笑,withoutboat怎么办?)总目标是提升Rust中所有web开发和框架之间的共享、兼容和改进。
Tide的愿景:
- 加强提供核心网络功能中充当「体力活」的crate,要确定并改进、标准化一批像http、url这样的基础库。
- 在这些基础库之上构建一个严肃的框架。理想情况下,只要可行就使用现成的crate,如果不合适,就自己创造一些小的、独立的crate。
这些均会记录到Tide的书中。并且这些工作都将是开放的,本篇文章就是这一系列的第一篇博文,如果你想参与这项工作的任何方面,请访问Discord上的WG-net-web频道!
初始主题:
基础服务API。
大多数语言生态系统最终都有一个关键的界面来讨论Web服务:Ruby有Rack,Python有WSGI,Java有Servlets等等。拥有这样的接口意味着你可以从底层Web服务器中分离Web框架。还可以提供可用于任何服务器和框架的通用底层中间件。现在tower-web已经开始这部分工作。简而言之,这种Service trait建模是通用的。
但当前的问题是:
- Service trait建模是在async/await之前设计的,可能需要一些更改。
- 还需要标准化HTTP处理,可以参考tower-web中的BufStream参与讨论。总的来说,Tide就是打算在这些现有抽象的基础上来实现标准化和改进。
路由策略。
当前路由策略一共有三种:
-
Endpoint-centric 路由。是Rocket和tower-web的方式。就是利用属性,比如#[get("/")],将对应函数设置为endpoint。
-
Table-of-contents路由,是Gotham, Rouille, 和 Actix Web采用的方式。
比如
route.request(vec![Get, Head], "/").to(index);
route.get_or_head("/products").to(products::index);
route.get("/bag").to(bag::index);
这种方式有助于处理多个endpoint的问题,但是它比前一种策略更重一些,并且从请求信息中提取信息可能没那么灵活。
- 自由格式组合的路由
就是Wrap采用的方式。在某种程度上,也可以称为无路由方法。endpoint和应用中其他函数没有什么区别。一切皆filter,你可以通过组合filter来构建你的服务。
// Just the path segment "todos"...
let todos = warp::path("todos");
// Combined with `index`, this means nothing comes after "todos".
// So, for example: `GET /todos`, but not `GET /todos/32`.
let todos_index = todos.and(warp::path::index());
// `GET /todos`
let list = warp::get2()
.and(todos_index)
.and(db.clone())
.map(list_todos);
// `POST /todos`
let create = warp::post2()
.and(todos_index)
.and(warp::body::json())
.and(db.clone())
.and_then(create_todo);
// Combine our endpoints, since we want requests to match any of them:
let api = list
.or(create);
// View access logs by setting `RUST_LOG=todos`.
let routes = api.with(warp::log("todos"));
现在谈这种方式的优缺点还有点早,所以这里没谈。(无关个人喜好)
Tide中的路由是什么方式?
Tide倾向于 Table-of-contents路由,因为它比endpoint-centric路由更容易模块化和扩展,比自由式路由更容易理解。
在下一篇文章中,将深入研究Rust中的 Table-of-contents式路由中出现的一些API设计问题,并研究模块化和共享的途径。
(小声BB: 预计2019年Rust在Web领域的应用将爆发。。。)
【重要】如何组织复杂的Rust代码库
这篇文章是Flare开发者在构建Flare这个复杂软件过程中,思考的一些Rust代码库相关的细节。
- 使用JetBrains CLion开发Rust
- 目前是使用Nightly版本,但指定了edition = 2018,但目标是等待stable Rust 2018。虽然目前使用了一些unstable 特性,但是越来越少了,Rust 2018版本对他们来说,已经非常适合使用。
- 依赖库。 可以到这里找到他们使用的依赖库。比较出名的有failure、serde、lazy_static、libc、rand等。
- 源码组织。 遵循Rust的传统,将项目构建为单独的crate。文章中包含了相关模块介绍。
- 管理unsafe代码。 它们在项目根模块添加了#![deny(unsafe_code)] ,但是自己实现了一个unsafe_block!宏:
macro_rules! unsafe_block {
($reason:tt => $body:expr) => {{
#[allow(unsafe_code)]
let r = unsafe { $body };
r
}};
}
- 在编写unsafe代码的时候使用这个宏,这就使得不安全的代码更具有审计性,达到了统一管理的目的。这个实践很棒。
- 管理cross-cutting concerns代码。 cross-cutting concerns来自于AOP的一个术语,叫横切关注点。这里其实是指那些在代码中复用的一些「工具类」函数或类型。代码越复杂,这种东西就会越多,需要好好管理它们。文章作者使用std_ext模块来统一管理这些「工具」
- 开发中可能会经常为结构体中增加新字段来解决一些问题,但有时候新加的字段,在一些方法里并没有被使用。所以 利用#![deny(unused_variables)]属性来限制结构体,如果出现这种在方法里没有被使用的字段,则会报错。从而提醒开发者,仔细考虑这个需求。
- 还有很多值得探索的地方; 包括与.NET互操作,跨平台打包,测试和模糊测试。
看得出来,Rust语言本身为开发大型复杂应用提供了很多工具。
期待后续文章。
Rust源码分析:crossbeam之ms_queue(1)
crossbeam源码分析系列文章。
crossbeam是官方核心成语Aaron编写的并发库,提供了mpmc channel、scoped thread、并发数据结构、扩展了标准库的原子类型、以及其他的一些工具。
文章里介绍的是crossbeam库中Michael-Scott非阻塞队列(lock-free)算法的Rust实现,MS-queue算法主要依赖于CAS原子操作。
并行化PNG压缩系列文章
出到了第五篇
From Rust to beyond系列: 与C交互
常见的Rust trait
文章罗列了常用的trait,非常适合初学者
评论区
写评论还没有评论