CppCMS 杂

同步与异步

放在 applications_pool 里面的都是 synchronous app,他们一般使用 factory 构造出来,其特点是其 context 被 cppcms 的 framework 构造好之后,根据匹配关系交由 threads_pool 中某个线程,该线程执行对应 applications_pool 中对应 application 的逻辑,也就是说对并发的请求,synchronous app 是直接依赖多线程来实现的。asynchronous app 自己就能 handle 并发请求,这意味着它们直接在 event loop 中接受请求,而并不通过 threads_pool。下面一段代码显示了一个 asynchronous app 的例子。

try {
  cppcms::service service (argc,argv);
  booster::intrusive_ptr<chat> c = new chat (service);
  service.applications_pool ().mount (c);
  service.run ();
} catch(std::exception const &e) {
    std::cerr << "Error: " << e.what () << std::endl;
    return 1;
}
return 0;

这个例子表明通过 intrusive_ptr(实际上是 boost.smart_ptr 里面的一个和 shared_ptr 类似的东西,被指向的对象自己拥有 ref count,通过 intrusive_ptr_add_ref 和 instrusive_ptr_release 两个函数来管理 ref count)产生一个 asynchronous app,并 mount 到 applications_pool。下面是一个比较典型的异步调用形式

booster::shared_ptr<cppcms::http::context> context=release_context ();
waiters_.insert (context);
context->async_on_peer_reset (
  bind (
    &chat::remove_context,
    booster::intrusive_ptr<chat>(this),
    context
  )
);

通过类似的方法可以将需要 long polling 的请求弄成这样避免等待。关于 context 其他的一些异步请求代码见这里

从这一点上来看,这篇批评 node.js 的文章是 make sense 的,即真正 asynchronous 是指将能够避免无谓等待的地方弄成避免等待(以做些别的事情),而不是说一味的把所有的事情都弄成 asynchronous(因为没有必要)。感觉 node.js 为程序员提供了一种非常方便切换到异步的方式,cppcms 相对还是更有难度一些。有时候“容易使用”很可能变成“过度使用”,这是使用 node.js 需要谨记的地方吧。但是程序员如何知道什么时候需要 synchronous call 什么时候需要 asynchronous call 呢?

与其他 web server 的配合

CppCMS 可以使用 FastCGI(特点是使用 socket 通信,具体的 spec 见这里) 与 SCGI(特点是使用 stream 实现,相对 FastCGI 更容易实现,具体的 spec 见这里)与其他的 web server 协同工作。看这个文档比较有意思的可能是 lighthttpdnginx 和 apache 这三个。apache 算是接触过一段时间,其他两个还不清楚,像 lighthttpd 应该算是轻量级的 web server(资源消耗少),而 nginx 算是为了高流量网站准备的也是比较 heavy 的东西了吧(似乎特点也是 asynchronous 机制,而 apache 是用 multi-threading、multi-processing 来解决的)。

plugin 的支持

前面的例子我们看到可以使用动态链接库提供 templates 的不同 rendering,这是一种比较直接、简单的 plugin,另有一种不知道是不是通过反射实现的(尚未提供)。现在的支持的方式一般是自己定义一个 interface,然后约定一些 function 供在 template 里面使用。这样做了之后,所有实现了这个 interface 的动态链接库理论上是可以运行时进行切换的(比如通过 ld 的一些函数来实现)。感觉上 plugin 这部分可能还是会依赖于 boost.reflection/extension 提供的一些手段(虽然 reflection/extension 还没正式进入 boost,啊为什么…)

static 文件的伺服

简单的 solution 就是配置一个 static root,对于某个 url 下面的文件处理引用的时候直接用 std::ifstream 读取内容返回即可。但是这样做有 security issue,比如传入的文件含有对路径的修改(如相对路径),为了 detect 这类问题,比较容易的做法是为指定路径下的文件进行控制(如修改文件名为某些 hash value)。另外也可以通过 boost.filesystem 的相关功能对给定路径进行确认,对非法路径进行 filtering。这个应该是很容易做成 app level 的共享的,并且是独立于各个应用的一个模块。不过 cppcms 和 django 的不同在于现在没有太多的 contribution(连这个 static 的模块好像都没现成的)。

booster 的 aio

这个东西前面也没仔细的研究过,但是从介绍里面看来和 boost.asio 还是不一样的。boost.asio 实际上也是一个 event-based 的 IO,现在不是很清楚的是到底 node.js/nginx 和 apache 的“具体差异”到底在哪里,难道只是前者更强调 event-based?booster.aio 是对 boost.asio 的简化(这个…),提供了比如 basic_io_device 可以 attach 到 std::cin 上,这个就可以为某些 event 添加需要的 callback function 了。

数据库

似乎 C++ 不像 Java/python 之类的有一些非常好用接口统一的 library 与数据库打交道,这方面 boost 似乎也没有提供一个比较理想的 binding,不知道这个情况在今后会不会有所解决。其实 web app 很多时候是需要有一个不错的 DB 的 middleware 将应用逻辑与 DB backend 分离的,CppCMS 似乎也没有一个明确的解决方案。找了一个 sqlite3 的 C++ 的 binding(sqlite3pp),风格据说和 boost 接近。django 这部分成熟的多,可以很容易的将 model 传入到 template 中。

——————–
Let a little water, I pray you, be fetched, and wash your feet, and rest yourselves under the tree:

Advertisements
CppCMS 杂

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s