haogongju、人人IT网、59n南龙、360doc不要抄我的烂博客了,私人备忘用。
我们需要了解系统的一些状态,比如,对riak这个NoSQL来说,我们需要了解bucket的当前存储状态。有时候也需要直接访问某个存储对象。这都可以通过HTTP和其他接口访问,HTTP是Riak Core提供最直接最方便的对外访问接口。
Riak Core通过webmachine实现对外提供HTTP/HTTPS访问接口。具体实现是riak_core_web模块,该模块非常简单对外提供了一个binding/1函数:返回了webmachine_mochiweb及其启动参数,也就是supervisor的child进程启动参数:
{Name, {webmachine_mochiweb, start, [Config]}, permanent, 5000, worker, [mochiweb_socket_server]}
这个tuple作为supervisor的child spec,最终结果是webmachine_mochiweb进程挂在riak_core_sup监管的进程树上(?)。
在此借用webmachine的概念用“web资源”表示Riak Core以及基于它开发的应用提供的HTTP接口。
web资源的列表
Web资源模块可以用webmachine_router:add_route/1函数动态加入,最终所有的路由(dispatch)会作为webmachine的环境变量dispatch_list的值。
引用
application:set_env(webmachine, dispatch_list, DispatchList)
这是一种很有趣的用法,可以看作是一种application范围的命名空间,变量存放在这个命名空间内,但是这里的变量是持久化的么?如果是写在app文件的env中当然是持久化的,但是缺点却是不能修改的。。。因此,这些变量应该是在每次启动时初始化值,而不是持久化来的。
从OO转来erlang的同学有时候会觉得不太适应,因为在OO中可以通过静态对象属性(私有或公有)很方便的保存某个变量,用的顺手了,来到erlang发现没有对应的对象的概念,勉强对应的是动态的erlang进程。而变量或者在进程间传递(某种Context,或者环境),或者在进程字典里,或者在ets里,又或者,与OO最相似的用法是利用参数化模块(parameterized module)。这里看到了另外一种变量的保存和传输方式:每个application管理着一个命名空间,变量存放在这个命名空间内。(不过本质上,这些变量最终还是保存在ets中的,不过是该application对应的application_controller,一个gen_server模式的进程,这是一种更高层次的进程,不像一般普通进程死掉了没关系大不了再来一个,这个进程死掉意味着整个应用都当掉了,所有与这个应用有关的进程也都会当掉。)
Riak Core提供了一个统一的、缺省的也是唯一的Web资源模块:riak_core_wm_urlmap。这个web资源只有一个用途:列出其它的web资源。(其实就是保存在webmachine的环境变量dispatch_list里的那些模块)。例如对于riak数据库,直接在浏览器中打开http://localhost:8098/时会看到这个列表,都是riak_kv提供HTTP接口,如图所示。
举个例子,对于riak这个NoSQL KV来说,riak_kv基于webmachine提供相关的HTTP访问接口(在riak_kv应用配置文件的applications属性,在riak_kv启动时会先确保这个属性列表值里的所有应用都已启动),riak_kv在启动时(riak_kv_app:start/2)通过webmachine_router:add_route/1将这些HTTP接口(riak_kv提供的web资源)注入到webmachine,如前所述,实际上是webmachine应用的环境变量dispatch_list,riak_core_wm_urlmap资源会将这些web资源显示出来。
顺便说一句,riak_kv的这些HTTP接口(每个接口其实是一个webmachine web资源)是在riak_kv_web中定义的,riak_kv_app:start/2函数通过这个模块获得这些web资源列表,riak_kv_web:dispatch_table/0函数为riak_kv提供了一个dispatch列表,这里列表中的web资源模块有统一的命名规则,都是riak_kv_wm_起头。
综上所述:通过webmachine_router:add_route/1添加web资源时,会自动将web资源添加到webmachine应用维护的一个内部变量中。riak_core提供了一个缺省web资源(riak_core_wm_urlmap),它会将这个变量中保存的路由表(或者说diapatch list)以列表的形式显示出来。