作为一种服务器语言,Rust出人意料地好

2020-07-13 14:39:24

在某种程度上,我厌倦了为我的博客和其他页面设置旧的静态站点生成器。每次我想要进行修改时,ssh都很烦人,sftp或sshfs所有的图像都很烦人,以此类推。上帝保佑,如果你想让别人写东西或做编辑,让我告诉你,当你告诉他,嘿,我会让你成为我服务器上的用户时,大多数人都不会特别高兴,把你的公钥给我,这样你就可以ssh了。

这就是我们的项目:一个小范围的博客,在这里,一些已经被信任的用户可以用markdown制作、编辑和发布新页面(由SimpleMDE提供的一个很好的markdown编辑器)。此外,我想要一个内置的简易版imgur,这样我就可以满足我自给自足的需要,而不会发疯。

因此,虽然我可以在一个下午用Django快速制作一些东西,但我也可以尝试其他语言。这个项目非常简单,我无法想象会受到任何语言生态系统的太多限制。而且我一直渴望在“铁锈”上写些实质性的东西。

几个月前,当我在研究我的选择时,Actix-web的维护人员带着一系列戏剧性事件辞职了。

至少从我阅读文档可以看出,它似乎更适合API,而不是提供模板化HTML的服务器。

有了上面的内容,我希望这是一个周末项目,而不是每周项目,所以电池越多越好。

我真的不想知道哪个异步库更好。请注意,每个异步库都有自己的库生态系统,这些库只与异步库一起工作,所以在您创建它之后要改变它是一个相当困难的决定。(#39;{##**$$})。

直到我开始研究这个项目,我才意识到在服务器上……。内存模型实际上非常简单!

您的大部分州都是由您的数据库处理的。我从来没有和借阅收银员打过架。我从来没必要这么做。在大多数情况下,所有东西都恰好只有一个所有者,并且恰好只有一个生命周期:处理请求的函数。

到目前为止,铁锈的宏观系统确实给我留下了深刻的印象。不仅有令人震惊的数量";仅仅是作品,而且它都是静态键入和编译的。

与Rocket最相似的是flask+所有flask邻接库(SQLAlChemy-flask等)。通过第三方集成的强大功能,Rocket提供了两个模板引擎(Handlebar和Tera,基本上就是JJIA2)、对相当多ORMS/DB驱动程序的数据库池支持,等等。

虽然我听说有人将其与Django/Rails相提并论,但它们似乎并没有真正朝着这个方向发展。Django/Rails故意将您(开发人员)置于比喻意义上的轨道上,从文件的位置到如何更新模型和视图的方方面面都规定了最佳实践。火箭不会这么做,我也不确定它是否应该这么做。

在很大程度上,我也有过这样的经历,如果它被编译了,它就会工作。我的大多数运行时错误都在模板中,顺便说一句,这是唯一不是静态类型的东西。

我想这才是真正让我吃惊的地方。对很多人来说,它就是管用的!。没有太多的样板语法,类型推断使您的函数保持干净,而且我在任何时候都没有编写任何生命周期注释。我的Rust服务器看起来真的与我的flask服务器或Django服务器没有什么不同,而且老实说,它看起来比我的Java服务器干净。所有这些都没有垃圾收集器或运行时。

接下来,我将谈一谈柴油,据我所知,它是目前可用的最成熟的ORM。虽然我确实有我的抱怨,但客观上这并不是什么坏事。我想这是更多的权衡,而迪塞尔选择了对魔术的轻描淡写。

首先,为每个表创建两个结构很烦人。您需要一个用来表示表,另一个用来插入(删除任何自动生成的列,如主键)。例如,我有

#[Deriate(Identifiable,Queryable,Associations,PartialEq,Debug,Serialize)]#[Belong_to(blogpost,foreign_key=";post_id";)]#[table_name=";tag";]pub struct tag{id:I32,tag_name:string,post_id:I32,}#[Derive(Insertable)]#[table_name=";tag";]pub结构标签{id:i32,tag_name:string,post_id:I32,}#[Derive(Insertable)]#[table_name=";tag";]pub。

此外,在某些ORM中,您编写表模型,ORM生成SQL迁移,而在柴油中,您手动编写SQL迁移,ORM生成包含映射的schema.rs文件。事实上,我并不太介意这一点。

DIESEL还只支持父子关系,您必须非常明确。在你的父母身上没有魔术字段,它会神奇地给你一个它的孩子的列表。不需要,您只需编写查询并调用它。从某种意义上说,它更像是使用稍微花哨一点的查询构建器。

从那样的魔力水平下降,可以说这并不是一件坏事。通过直白,你可以防止用户过于相信这种魔术,并像N+1选择那样搬起石头砸自己的脚。

但我也不会说它没有让我慢很多。老实说,编写连接是一件令人头疼的事情。也许事情应该是这样的,但也许这也导致了新一代NoSQL数据库的出现。🤷。

#[POST(";/Upload";,Data=";<;Data>;)]//签名要求请求有一个`Content-Type`fn multipart_Upload(CONT_TYPE:&;CONTENTTYPE,Data:Data)->;Result<;Stream<;Cursor<;Vec<;u8>;>;>;,自定义字符串>;{//此检查和下一个检查可以作为请求保护来实现,但如果!cont_type.is_form_data(){return err(Custom(status::BadRequest,";Content-Type Not Multipart/Form-Data";.into();}let(_,edge)=cont_type.params().find(|&;(k,_)|k==&),则此检查和下一次检查似乎只是//比必要的多个样板。find(|&;(状态::BadRequest,&34;Content-Type Not Multipart/Form-Data";.into()。).OK_or_ELSE(||Custom(Status::BadRequest,";`Content-Type:Multipart/Form-Data`边界参数未提供";.into()?)?;Match Process_Upload(边界,数据){OK(Resp)=>;OK(Stream::From(Cursor::New(Resp),Err(Err)=>;err(Custom(Status::InternalServerErr。str,data:data)->;io::result<;vec<;u8>;>;{let mut out=vec::new();//保存所有字段,任何超过10KB的字段都将转到临时目录//条目可以实现FromData,但这将使//对文件的保存方式没有控制权;multipart将是一个很好的实施候选,但Match multipart::with_body(data.open(),edge).save。MUT OUT)?,PARTIAL(PARTIAL,REASON)=>;{Writeln!(Out,";请求部分处理:{:?}";,Reason)?;如果让Some(Field)=Partial.Partial{Writeln!(Out,";,field.Soure.Headers)?;}PROCESS_ENTRIES(PARTAL.ENTRIES,&;MUT OUT)?},错误(E)=>。

现在,公平地说,火箭的版本是0.4.5。从这个GitHub问题开始,0.5.0开始支持多部分表单。但这并不能改变这样一个事实,即目前的图书馆仍然有些不成熟。它们缺乏一些边缘功能,特别是对于提供模板化HTML的更传统的Web服务器,而不是纯API服务器或SPA。

铁锈的错误是相当好的,通常。但那是在你进入那些试图做更多事情的图书馆之前。我碰到了一些..。有趣的错误消息,主要来自Rocket和柴油中的宏。举个例子,看看这个。

特征绑定`(I32,std::String::String,I32,I32,std::String::String,I32,I32):diesel::Queryable<;diesel::sql_types::Nullable<;(DIESEL::SQL_TYPES::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPES::TEXT,DIESEL::SQL_TYPE::INTEGER)>;,DIESEL::SQLITE::Sqlite>;`不满足特征`diesel::Queryable<;diesel::sql_types::Nullable<;(DIESEL::SQL_TYPES::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPES::TEXT,DIESEL::SQL_TYPE::INTEGER)>;,DIESEL::SQLite::Sqlite>;`(I32,std::string::string,I32,I32,std::String::String,I32,I32)`help没有实现`help:找到以下实现:<;(A,B,C,D,E,F,G,H,I)as DIESEL::Queryable<;(SA,SB,SC,SD,SE,SF,SG,SH,SI),__DB>;>;注意:由于`diesel::Queryable<;diesel::sql_types::Nullable<;(diesel::sql_types::Integer,DIESEL::SQL_TYPE::TEXT,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::TEXT,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::INTEGER)>的实施要求,必填项;,`diesel::Queryable<;((diesel::sql_types::Integer,DIESEL::SQL_TYPE::Text,DIESEL::SQL_TYPE::INTEGER),DIESEL::SQL_TYPE::Sql_Types::Null<;(DIESEL::SQL_TYPES::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPES::TEXT,DIESEL::SQL_TYPE::INTEGER),DIESEL::SQLite::Sqlite>;`for`(Posts::Tag,Posts::blogpost)`备注:由于`diesel::query_dsl::LoadQuery<;diesel::SqliteConnection,(Posts::Tag,Posts::blogpost)>;`对`diesel::query_builder::SelectStatement<;diesel::query_source::joins::JoinOn<;diesel::query_source::joins::Join<;schema::tags::table,Schema::blogpost::Table,DIESEL::QUERY_SOURCE::JOINS::LeftOuter>;,diesel::expression::operators::Eq<;schema::blogposts::columns::id,Schema::Tags::Columns::Post_id>;,diesel::query_builder::select_clause::DefaultSelectClause,diesel::query_builder::distinct_clause::NoDistinctClause,diesel::query_builder::where_clause::WhereClause<;diesel::expression::operators::Eq<;schema::tags::columns::tag_name,DIESEL::Expression::Bound::Bound<;DIESEL::SQL_TYPE::TEXT,&;str>;>;`rustc(E0277)posts.rs(477,103):表示特征`diesel::Queryable<;diesel::sql_types::Nullable<;(DIESEL::SQL_TYPES::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPE::INTEGER,DIESEL::SQL_TYPES::TEXT,DIESEL::SQL_TYPE::INTEGER)>;,DIESEL::SQLite::Sqlite>;`(I32,std::string::string,I32,I32,std::string::string,I32,I32)`未实现`。

有一次我想让cookie过期一个月,因为我很可能会在我的实际个人电脑上主要使用它。所以我在文档里找了相应的火箭物品。

好的,它想要一个……。TM?这鬼东西是TM吗?那么,让我们来看一下这个例子。

看起来不错,那正是我想要的.。在期限上减去11个月,但那是可以的。

显然,std::time中的那个不是正确的!好的,我想我要向我的node_module Cargo.toml添加另一个库。

不,这个问题的答案要么不明显,要么可能我只是瞎了眼,因为我在其他任何地方都看不到任何有模糊相似行为的东西。

说到node_module,老实说,有些Rust生态系统让我想起了NPM。在开始编写代码之前,我的最终发布版本需要编译267个不同的库,而这正是我简单的小博客引擎所需要的。

我情不自禁地想,如果其中一个叶依赖关系受到损害,我就不可能意识到这一点。但我确信它确实减少了构建大小,尽管可能不会减少构建时间,因为所有内容都是静态链接的,这样就可以非常准确地包含您需要的内容。它也不像C语言有一个丰富多彩的标准库。但是,只有当所有管理图书馆的人都试图将自己的依赖保持在尽可能低的水平时,这才是正确的。

我会推荐别人用Rust编写他们的下一台服务器吗?不是的。生态系统还没有完全到位,而且大多数服务器仍将受到I/O的限制,因此速度提升可能不会有太大影响。

但是,一旦生态系统成熟,老实说,我认为Rust是编写服务器的一种很好的语言。你得到了速度和安全,而且老实说,你不需要支付通常与借阅检查员抗争(或至少考虑到)的价格。有时我真的觉得我是在用稍微冗长一点的蟒语写作。这是非常有趣的,我对期待已久的火箭0.5.0版本感到非常兴奋。

不过,我很确定这将是一个结账功能分支升级,而不是单行升级。

我对我最终得到的相当满意。一台小而可爱的服务器,它完全按照它需要的方式运行,没有在后台运行无关的运行时