最近我在微博转发了亚马逊对Rust和Go语言的对比。亚马逊发文力捧 Rust ,Go 技术负责人:别“拉踩”我们https://weibo.com/2150275531/LlkxkvTrl
AWS的文章对Rust的推崇溢于言表。引起了业内的震动。再次把cloud native, green programming language 这些问题推到舆论风口。那我们就多关注一下Rust
Rust学习并不是很容易。如果大家学习过C++的语言特性,并且深入了解C++的标准库auto pointer和Boost扩展库里的smart pointer的话,我觉得大家会比较容易了解Rust的强类型和内存安全的一些考虑。这部分大家可以比较学习,横向比较确实是一种提高自己的方法。
但是真正用Rust做一些企业真实的应用。我觉得只是学习语言特性是不足够的。底层库或者程序框架的开发者对语言特性的要求比较高。而我们要跨越谈论语言特性,和其他语言之间做比较的时候。我们还是要通过语言的生态,企业开发的支持来做一些探索。这样,才能真正落地,应用到生产环境里。
我们探索的脚步不能停止。我将对一些比较重要的问题展开讨论。
在学习Rust的时候,我们再语言入门的时候一定有很多的资料。我可以推荐大家看一些基本的资料。
Rust学习资源和路线_weixin_34174132的博客-CSDN博客Rust学习资源和路线来源 https://rust-lang-cn.org/article/23学习资源The Rust Programming Language堪称Rust的"The Book",是目前最权威的Rust系统教程,入门必读。Rust by Example实例化的讲解方法,通过一个个可实际运行的例子去介绍Rust的特性和用法,有的时候,代码是最好的老师。Frequen...https://blog.csdn.net/weixin_34174132/article/details/85975606?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164826295516780261980079%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164826295516780261980079&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-85975606.142%5Ev5%5Epc_search_result_cache,143%5Ev6%5Econtrol&utm_term=rust%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF&spm=1018.2226.3001.4187
Rust学习资料汇总_chirpyli的博客-CSDN博客_rust学习列举一些学习Rust的好资料,方便平常学习与查阅。大部分文档在官网Grow with Rust一节都有列出,另一部分是平常学习时涉及到的文档资料。The Rust Programming Language这本书当然是要第一本阅读的了,入门首选。Rust对单元测试的支持是非常友好的,可参考Writing Automated Tests这一章。Rust by Example通过代码示例...https://blog.csdn.net/s_lisheng/article/details/105778760?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164826295516780261980079%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164826295516780261980079&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-5-105778760.142%5Ev5%5Epc_search_result_cache,143%5Ev6%5Econtrol&utm_term=rust%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF&spm=1018.2226.3001.4187
在官方的教程文档中,我们可以看到multi-thread的用处和如何使用线程池。官方文档示例里给出了跟好的例子。
当然如果我们需要一个有生产强度的并行库。我们可以使用Rayon, tokio_threadpool等等。
GitHub - rayon-rs/rayon: Rayon: A data parallelism library for RustRayon: A data parallelism library for Rust. Contribute to rayon-rs/rayon development by creating an account on GitHub.https://github.com/rayon-rs/rayon
GitHub - gatoWololo/tokio-threadpool-0.1.18: Modified version of tokio-threadpool for Servo-rr-channel compatibility.Modified version of tokio-threadpool for Servo-rr-channel compatibility. - GitHub - gatoWololo/tokio-threadpool-0.1.18: Modified version of tokio-threadpool for Servo-rr-channel compatibility.https://github.com/gatoWololo/tokio-threadpool-0.1.18
Rust里最大名鼎鼎的一部框架就是 Tokio。这个框架是很多框架的基础。框架本身的文档还是非常的详尽。而且在Github项目代码目录,有非常详细的实例程序。我们可以在 examples 这个位置找到。我是非常推崇直接通过例子来学习框架。
对于异步处理框架,我们还是需要仔细了解异步框架的原理。大家可以看一下 Async in Depth 来更深入的了解Async的实现原理。这对异步系统的理解和调优相关的任务会有比较好的帮助。
Tokio 本身提供了一个 gRPC 的实现 Tonic。用Tonic开发其实也是比较容易的。我认为gRPC本身的效率还是非常高的。
我们可以参照这篇文章实现一个基本的三层应用后端。How to use gRPC with Rust Tonic and Postgres database with examples - DEV CommunityIn this post, we will learn how to use Rust Tonic gRPC crate and implement CRUD with Postgresql... Tagged with rust, tonic, postgres, grpc.https://dev.to/steadylearner/how-to-use-grpc-with-rust-tonic-and-postgres-database-with-examples-3dl7
或者使用tonic + sqlx来实现数据库连接也可以。
hhttps://github.com/rezmuh/todo-tonic-sqlx-refinery-barrelhttps://github.com/rezmuh/todo-tonic-sqlx-refinery-barrelhttps://github.com/rezmuh/todo-tonic-sqlx-refinery-barrel当然Tonic本身的examples也可以给大家大的帮助。
Tracing提供了一个比较统一日志体系。他的重要性和java里的log4j一样。所以这也是基本的企业应用的基础件。日志的重要性大家都知道吧?
数据库的重要性肯定是不言而喻的。Rust的数据库支持有哪些呢?下面这个文章给了我们一个比较全面的介绍。
11 database drivers and ORMs for Rust that are ready for production - LogRocket Bloghttps://blog.logrocket.com/11-database-drivers-and-orms-for-rust-that-are-ready-for-production/
GitHub - diesel-rs/diesel: A safe, extensible ORM and Query Builder for RustA safe, extensible ORM and Query Builder for Rust. Contribute to diesel-rs/diesel development by creating an account on GitHub.https://github.com/diesel-rs/diesel
SQLX是本身是一个基于Tokio的异步框架。所以应该基本上可以其他的异步框架进行使用。
GitHub - launchbadge/sqlx: The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL. The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL. - GitHub - launchbadge/sqlx: The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL.https://github.com/launchbadge/sqlx
SQLX的好处就是比较纯粹,我们还是需要写SQL来完成工作。但是所有的语法检查,sql准备都在编译期做好了。在执行的时候效率非常高。
GitHub - rbatis/rbatis: Rust High Performance compile-time ORM(RBSON based)Rust High Performance compile-time ORM(RBSON based) - GitHub - rbatis/rbatis: Rust High Performance compile-time ORM(RBSON based)https://github.com/rbatis/rbatis/这个基本上就是一个MyBatis的 Rust版本。具体例子可以看官方的 examples。这样的话从 java 转型过来的程序员就非常适应这种数据库访问方式。
比较有意思的是RBatis的底层就是使用了sqlx,所以相对来说给sqlx添加了一个ORM层。RBatis所有的sql语法检查准备也都是在编译期完成。保持性能方面的优势。
现在大多数的后端应用还是在使用无状态的微服务框架,现在这些框架已经基本上比较成熟。所以在本人的gitee里面fork了并且维护了一个国外的实现。
kanban: 由于对spring框架和java技术栈约来约笨重。我们在承担不必要的成本。所以该项目开始讨论其他的方案。特别是针对Rest API实现的方案。https://gitee.com/raymondshen/kanban
这里面以快捷开发的看板应用为例,演示了如何使用不同的框架。和Rust有关的是如下两种。
同步框架: Diesel + Rocket
异步框架: sqlx + actix-web
当然我非常推荐大家仔细阅读一下原作者的说明。
rust-blog/restful-api-in-sync-and-async-rust.md at master · pretzelhammer/rust-blog · GitHubEducational blog posts for Rust beginners. Contribute to pretzelhammer/rust-blog development by creating an account on GitHub.https://github.com/pretzelhammer/rust-blog/blob/master/posts/restful-api-in-sync-and-async-rust.md
他深入的分析了这些框架之间的异同。得到了一个并不让人惊讶的结论,异步框架吞吐量占有而同步系统延迟占优。
这里我在sqlx-actix-web的基础上添加了i18n的支持。如果您面临的是国际化的后端应用。不妨可以看一下。
如果大家希望快速有生产力的话,我建议大家做出一定的选择,直接跳过复杂的Rust语言特性。直接使用框架写后端应用。这样学习的话会表有成果,也能鼓励人不断在实践中进步。这比一下子掉到语言特性的坑里要好多了。
另一个比较全面的例子是在这里,而且这个例子对数据程序的架构给了一定的示范作用。非常值得学习。
GitHub - jamesjmeyer210/actix_sqlx_mysql_user_crud: A user crud written in Rust, designed to connect to a MySQL database with full integration test coverage.A user crud written in Rust, designed to connect to a MySQL database with full integration test coverage. - GitHub - jamesjmeyer210/actix_sqlx_mysql_user_crud: A user crud written in Rust, designed to connect to a MySQL database with full integration test coverage.https://github.com/jamesjmeyer210/actix_sqlx_mysql_user_crud
比较重要的一点,是这个例子对数据库链接进行了多线程的封装。这样避免了之前案例中的问题。请关注下面 AppState 的初始化方法。这里也用了 Arc::new 来创建数据库连接的引用计数。
use actix_web::{web, App, HttpServer};
use sqlx_user_crud::config::Config;
use sqlx_user_crud::dao::Database;
use sqlx_user_crud::{controller, AppState};
use std::sync::{Arc, Mutex};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("=== SQLX User CRUD ===");
// Read in the configuration file.
// In small projects this can be a local configuration, but in more sophisticated systems, it is
// best practice to keep the configuration file on a remote server where it can be retrieved
// with an http request.
let config_file: &'static str = "config.json";
let config = Config::from_file(config_file);
println!("Using configuration file from {0}", config_file);
// Connect to the database
let db_context = Database::new(&config.get_database_url()).await;
println!("Connected to database: {0}", config.get_database_url());
// Instantiate the app_state. This application state will be cloned for each Actix thread but
// the Arc of the DbContext will be reused in each Actix thread.
let app_state = web::Data::new(AppState {
connections: Mutex::new(0),
context: Arc::new(db_context),
});
// Start the web application.
// We'll need to transfer ownership of the AppState to the HttpServer via the `move`.
// Then we can instantiate our controllers.
let app = HttpServer::new(move || {
App::new()
.app_data(app_state.clone())
.configure(controller::init_index_controller)
.configure(controller::init_user_controller)
.configure(controller::init_group_controller)
})
.bind(config.get_app_url())?;
println!("Listening on: {0}", config.get_app_url());
app.run().await
}
如果大家感兴趣,也可以看一下这个例子里有关 Module, Dao, Controler 的分层考虑。会比较有启发。 在下面研发自动化的时候我们还会在 sql_reverse 这一节进行更详细的说明。
rbatis和Actix-web配合的例子如下:
#![allow(unused_must_use)]
#[macro_use]
extern crate rbatis;
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use std::sync::Arc;
use rbatis::crud::CRUD;
use rbatis::rbatis::Rbatis;
#[crud_table]
#[derive(Clone, Debug)]
pub struct BizActivity {
pub id: Option,
pub name: Option,
pub pc_link: Option,
pub h5_link: Option,
pub pc_banner_img: Option,
pub h5_banner_img: Option,
pub sort: Option,
pub status: Option,
pub remark: Option,
pub create_time: Option,
pub version: Option,
pub delete_flag: Option,
}
impl Default for BizActivity {
fn default() -> Self {
BizActivity {
id: None,
name: None,
pc_link: None,
h5_link: None,
pc_banner_img: None,
h5_banner_img: None,
sort: None,
status: None,
remark: None,
create_time: None,
version: None,
delete_flag: None,
}
}
}
async fn index(rb: web::Data>) -> impl Responder {
let v = rb.fetch_list::().await.unwrap_or_default();
HttpResponse::Ok()
.insert_header(("Content-Type", "text/json;charset=UTF-8"))
.json(v)
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
//log
fast_log::init(fast_log::config::Config::new().console());
//init rbatis . also you can use pub static RB:Lazy = Lazy::new(||Rbatis::new()); replace this
log::info!("linking database...");
let rb = example::init_sqlite_path("").await;
let rb = Arc::new(rb);
log::info!("linking database successful!");
log::info!("start on http://127.0.0.1:8080");
//router
HttpServer::new(move || {
App::new()
//add into actix-web data
.app_data(web::Data::new(rb.to_owned()))
.route("/", web::get().to(index))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
这里BizActivity本身也可以通过sql_reverse 自动生成。请查看下面的相应章节。
Actor模式可以构建比较复杂的CQRS模式的应用。并且完成无锁机制的同步。最典型的框架是Erlang,Akka等虚拟机系统。在Rust语言上实现Actor模式,对我们来讲还是非常有意思的。
我推荐大家深度关注Actix。早在2020年,Rust语言也涌现出很多不同的Actor模式的实现。但是尘归尘,土归土,现在还在积极维护的看起来只有Actix了。如果有其他的服务实现,我觉得大家也可以留言推荐给我。我对此的看法是Actor模式非常适合大型企业后端应用,特别是有状态的应用。而Actix现在也助推actix-web框架,主要还是考虑现在微服务框架入门比较容易。而大型企业应用后端还是JVM的天下。Actix-actor在一定程度上是单机系统,只是考remote特性手工组建集群相对还是对架构师要求太高。但是,这不影响我对Actor模式的热情。还是会介绍一下。
在 Arbix 的实现离,Arbiter是一个调度单元。为了能够演示多个Arbiter的使用,下面的代码段还是非常有用的。
extern crate actix;
use actix::prelude::*;
struct Fibonacci(pub u32);
struct SomeActor;
impl Actor for SomeActor {
type Context = Context;
}
impl Message for Fibonacci{
type Result = Result;
}
impl Handler for SomeActor {
type Result = Result;
fn handle(&mut self, msg: Fibonacci, context: &mut Self::Context) -> Self::Result {
println!("working on fib({})", msg.0);
let mut sum=0;
if msg.0 == 0 {
Err(())
} else if msg.0 == 1 {
Ok(1)
} else {
for j in 1..1000000 {
let mut i = 0;
sum = 0;
let mut last = 0;
let mut curr = 1;
while i < msg.0 - 1 {
sum = last + curr;
last = curr;
curr = sum;
i += 1;
}
}
Ok(sum)
}
}
}
fn main() {
let sys = System::new();
let a1 = Arbiter::new();
let a2 = Arbiter::new();
let a3 = Arbiter::new();
let execution1 = async {
println!("exec 1 created");
let sa = SomeActor {}.start();
for n in 2..80 {
sa.do_send(Fibonacci(n));
}
};
let execution2 = async {
println!("exec 2 created");
let sa = SomeActor {}.start();
for n in 2..80 {
sa.do_send(Fibonacci(n));
}
};
let execution3 = async {
println!("exec 3 created");
let sa = SomeActor {}.start();
for n in 2..80 {
sa.do_send(Fibonacci(n));
}
};
a1.spawn(execution1);
a2.spawn(execution2);
a3.spawn(execution3);
sys.run();
}
examples/websockets/chat-broker at master · actix/examples · GitHubCommunity showcase and examples of Actix ecosystem usage. - examples/websockets/chat-broker at master · actix/exampleshttps://github.com/actix/examples/tree/master/websockets/chat-broker这个例子之所以重要,主要是他是Actix框架位数不多的接近实战的官方示例。而这个例子很好的演示了 WebSocket Session, Actor, Arbiter, SystemService, Supervied之间的配合。堪称难能可贵。这也体现了Artix框架设计的精妙。
下面是我们节选一下main.rs里的代码。
use actix_files::{Files, NamedFile};
use actix_web::{middleware::Logger, web, App, Error, HttpRequest, HttpServer, Responder};
use actix_web_actors::ws;
mod message;
mod server;
mod session;
use session::WsChatSession;
async fn index() -> impl Responder {
NamedFile::open_async("./static/index.html").await.unwrap()
}
async fn chat_ws(req: HttpRequest, stream: web::Payload) -> Result {
ws::start(WsChatSession::default(), &req, stream)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
log::info!("starting HTTP server at http://localhost:8080");
HttpServer::new(move || {
App::new()
.service(web::resource("/").to(index))
.service(web::resource("/ws").to(chat_ws))
.service(Files::new("/static", "./static"))
.wrap(Logger::default())
})
.workers(2)
.bind(("127.0.0.1", 8080))?
.run()
.await
}
大家可以注意代码中 workers(2) 这个调用。由于Session本身就是Actor,所以,多少个 worker 也就启动了多少个 Arbiter。
通过lldb我们可以看到这两个Arbiter的存在。
chat-broker % lldb ../../target/debug/server
(lldb) target create "../../target/debug/server"
Current executable set to '/Users/raymond/src/rust/examples/target/debug/server' (arm64).
(lldb) run
Process 5532 launched: '/Users/raymond/src/rust/examples/target/debug/server' (arm64)
[2022-03-27T06:36:51Z INFO server] starting HTTP server at http://localhost:8080
[2022-03-27T06:36:51Z INFO actix_server::builder] Starting 2 workers
[2022-03-27T06:36:51Z INFO actix_server::server] Actix runtime found; starting in Actix runtime
Process 5532 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00000001af84ac40 libsystem_kernel.dylib`kevent + 8
libsystem_kernel.dylib`kevent:
-> 0x1af84ac40 <+8>: b.lo 0x1af84ac60 ; <+40>
0x1af84ac44 <+12>: pacibsp
0x1af84ac48 <+16>: stp x29, x30, [sp, #-0x10]!
0x1af84ac4c <+20>: mov x29, sp
Target 0: (server) stopped.
(lldb) thread list
Process 5532 stopped
* thread #1: tid = 0xfd860a, 0x00000001af84ac40 libsystem_kernel.dylib`kevent + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
thread #2: tid = 0xfd864f, 0x00000001af84ac40 libsystem_kernel.dylib`kevent + 8, name = 'actix-rt|system:0|arbiter:0'
thread #3: tid = 0xfd8650, 0x00000001af84ac40 libsystem_kernel.dylib`kevent + 8, name = 'actix-rt|system:0|arbiter:1'
thread #4: tid = 0xfd8651, 0x00000001af84ac40 libsystem_kernel.dylib`kevent + 8, name = 'actix-server acceptor'
(lldb)
就此,我们看到了一些Actix的一些内部机制。但是最好的学习方法还是源代码。这里不再详述。
使用websocket-chat-server,进行扩充,控制好线程模型,我们很容易得到一个效率还不错的行情分发系统。这以后我们会尝试,并且和go语言的实现进行对比。
GitHub - atomix-team/actix-web-prometheus: Prometheus middleware for actix webPrometheus middleware for actix web. Contribute to atomix-team/actix-web-prometheus development by creating an account on GitHub.https://github.com/atomix-team/actix-web-prometheus这个项目是用了最为流行的 tikv/rust-prometheus进行了针对Actix的适配。很值得尝试。使用方法确实也不困难。本身项目代码也不多,有问题自己动手改吧。哈哈
use std::collections::HashMap;
use actix_web::{web, App, HttpResponse, HttpServer};
use actix_web_prometheus::{PrometheusMetrics, PrometheusMetricsBuilder};
fn health() -> HttpResponse {
HttpResponse::Ok().finish()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let mut labels = HashMap::new();
labels.insert("label1".to_string(), "value1".to_string());
let prometheus = PrometheusMetricsBuilder::new("api")
.endpoint("/metrics")
.const_labels(labels)
.build()
.unwrap();
HttpServer::new(move || {
App::new()
.wrap(prometheus.clone())
.service(web::resource("/health").to(health))
})
.bind("127.0.0.1:8080")?
.run()
.await?;
Ok(())
}
对于Sqlx,其实没有给出比较完善的ORM能力,所以我们使用sql_reverse来帮助我们。大家可以找到这个项目。他非常新。
GitHub - ptechen/sql_reversehttps://github.com/ptechen/sql_reverse我们为sqlx的model代码生成写了专门的template:
use serde::{Deserialize, Serialize};
use sqlx::mysql::MySqlRow;
use sqlx::{FromRow, Row};
{% if table.comment -%}
/// {{ table.comment }}
{% endif -%}
{% for index in table.index_key -%}
/// 索引:{{index}}
{% endfor -%}
#[derive(Serialize, Deserialize, PartialEq, Clone)]
pub struct {{ table.struct_name }} {
{%- for v in table.fields %}
{% if v.comment -%}
/// {{ v.comment }} {% if v.database_field_type %} field_type: {{ v.database_field_type }}{% endif %}{% if v.default %} default: {{ v.default }}{% endif %} {% if v.default == '' %} default: ''{% endif %}
{% endif -%}
{% if v.is_null == 1 -%}
pub {{ v.field_name }}: Option<{{ v.field_type }}>,
{%- else -%}
{% if v.field_type == 'NaiveDateTime' -%}
pub {{ v.field_name }}: Option<{{ v.field_type }}>,
{%- else -%}
pub {{ v.field_name }}: {{ v.field_type }},
{%- endif -%}
{%- endif -%}
{%- endfor %}
}
impl<'c> FromRow<'c, MySqlRow<'c>> for {{ table.struct_name }} {
fn from_row(row: &MySqlRow) -> Result {
Ok({{ table.struct_name }} {
{%- for v in table.fields %}
{{ v.field_name }}: row.get( {{ loop.index0 }} ),
{%- endfor %}
})
}
}
大家可以一试。
这是一个比较有效的模版引擎。可以帮助我们做代码生成。也是sql_reverse的后端引擎。
GitHub - Keats/tera: A template engine for Rust based on Jinja2/DjangoA template engine for Rust based on Jinja2/Django. Contribute to Keats/tera development by creating an account on GitHub.https://github.com/Keats/tera
rust项目的代码安全审计可以通过 cargo audit 进行审计。这里是公开的rust库的安全建议列库。这个建议库还是得到了很好的维护。
GitHub - rustsec/advisory-db: Security advisory database for Rust crates published through crates.ioSecurity advisory database for Rust crates published through crates.io - GitHub - rustsec/advisory-db: Security advisory database for Rust crates published through crates.iohttps://github.com/RustSec/advisory-db
如何安装和使用 cargo audit,可以参考这个文档:
rustsec/cargo-audit at main · rustsec/rustsec · GitHub
下面是我们针对actix-net进行审计的结果。发现了一个已经不被维护的库。
~/rust/actix-net
cargo audit
Fetching advisory database from `https://github.com/RustSec/advisory-db.git`
Loaded 421 security advisories (from /Users/user1/.cargo/advisory-db)
Updating crates.io index
Scanning Cargo.lock for vulnerabilities (214 crate dependencies)
Crate: serde_cbor
Version: 0.11.2
Warning: unmaintained
Title: serde_cbor is unmaintained
Date: 2021-08-15
ID: RUSTSEC-2021-0127
URL: https://rustsec.org/advisories/RUSTSEC-2021-0127
Dependency tree:
serde_cbor 0.11.2
└── criterion 0.3.5
└── actix-codec 0.5.1
├── actix-tls 3.0.4
└── actix-server 2.1.1
└── actix-tls 3.0.4
warning: 1 allowed warning found
Rust不仅能够在后端开发中得到大量应用。还可以在前端开发中使用。当前我们的架构基本上是这么来做的。
如果我们需要通过安装程序发布APP, 那外层,我们可以使用Tauri作为对操作系统适配的层。同时Tauri也提供各个不同操作系统安装包的制作。当然这个层具有一定跨平台的能力。Tauri也有相应的框架实现一些本地方法有WebBrowser调用。当前Tauri支持桌面版本的开发,也逐步会支持移动端开发。如果Tauri支持移动端,那它的使用场景就更加丰富了。
Tauri是一个基于Rust开发的项目。由于Rust本身的特性,Tauri的执行效率非常高,并且安装包非常小。
Build smaller, faster, and more secure desktop applications with a web frontend | Tauri AppsTauri is a framework for building tiny, blazing fast binaries for all major desktop platforms. Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.https://tauri.app/
而在WebBrowser里面,主要还是使用JS进行UI的开发。开发基本上就是按照Web开发的模式。实际上就是Tauri使用WebPack来在本地执行一个Http服务器,而浏览器加载本地站点服务。而对Tauri实现的扩充本地方法,JS会做好包装。
WebAssembly实际上是可以在WebPack中进行打包发布的。WebAssembly不仅支持Rust,还支持很多主流语言。这里我们偏重Rust。当然Web Assembly 并不只是用在当前的场景。还可以用在大多数的Web开发场景里。对我们来讲,使用Web Assembly的主要优势就是在一些机密的算法特别是加密的方法中,编译成二进制代码发布,可以保护我们的算法不被反向工程而被破译和窃取。
这里有很多资料帮助我们使用Rust来进行 WebAssembly开发:
WebAssembly - Rust Programming Language A language empowering everyone to build reliable and efficient software.https://www.rust-lang.org/what/wasm
选择使用Raft的同学,在很大程度上都会考虑性能要求比较高的关键应用。而关键应用除了对性能要求比较高以外,还会考虑稳定性。通过集群的配置提高可用性是一个非常关键的技术。所以,我们会对集群进行进一步的讨论探索。
这是一个实验项目,我们暂时还没有深入研究。但是如果真的能达到Akka集群的水平,我们还是非常期待的。为了这个理想,大家也去给人点个星星,鼓励一下呗。
GitHub - pengwin/actix-raft-clusterContribute to pengwin/actix-raft-cluster development by creating an account on GitHub.https://github.com/pengwin/actix-raft-cluster
另外一个实验项目是 actix_telepathy。作者 Phillip Wenig 是Hasso Plattner Institute的软件系统专业的博士生。有问题可以向他咨询。祝愿这个项目越来越好。这样我们就有基于Rust的Actor集群可用了。
actix_telepathy - RustActix-Telepathy is an extension to Actix that enables remote messaging and clustering support.https://docs.rs/actix-telepathy/latest/actix_telepathy/这里有一个例子可以知道项目如何运作。
https://github.com/wenig/telepathy-examples
这篇文章我们叙述了如何使用Raft来实现高可用的高性能撮合引擎。有兴趣的架构设计师,软件设计师同学我们可以一起探讨。原子多播是撮合引擎的正解,当前国际上比较有名的金融交易所都是延续这个设计方法。我们有幸通过开源项目低成本实现源自多播的撮合引擎,也说明开源项目的不断发展。
Raft in Rust (原子多播+撮合引擎)_Raymond-Shen的博客-CSDN博客
https://speakerdeck.com/lukemathwalker/writing-enterprise-software-a-rust-experiment
rust-blog/restful-api-in-sync-and-async-rust.md at master · pretzelhammer/rust-blog · GitHub