在programming in Erlang中 16章最后给出了my_bank.erl的一个gen_server 实现. 当时一直在琢磨分布式的问题.把C/S分离.后来做了测试. gen_server实现的6个必要条件是 start_link , init , handle_call , handle_cast , handle_info , terminate.
换句话说,这是最基本的gen_server实现. 那么我们只需要把这6个函数放在一个执行在服务器端的模块里.
然后其他逻辑就可以转移到客户端节点了.
而客户端的主要逻辑是:
gen_server:call(Name,Request).
这样一个部署逻辑就实现了. 在具体code过程中,
server:start_link 的Name 要用 {global,arbitary_atom}.
client:gen_server:call 的Name 要用 {global,arbitary_atom}.
最后集群启动 erl -name id@domain
发送简单的 net_adm:ping(server_id@domain).
(其实server ping client 也行,但是对于伸缩性集群来说,新节点加进来的时候,当然第一行动是它发出请求,而不是server.所以这里应当养成良好习惯)
这一步的作用是建立了节点之间的通信,在完成之后,节点间会把global注册了的全局名称发布到集群中.
gen_server的分布式结构就完成了. 当我们构建一个强大多应用的服务器时,就可以把gen_server的逻辑分成N部分,然后部署到N个节点中.
这样,ERLANG的巨大威力就完美的发挥了.
Wednesday, December 17, 2008
Monday, December 8, 2008
Erlang Mapreduce分析
最近在研究Erlang上的MapReduce框架. 本段代码摘自<>20章 Multicores Programming.
开始----
-----完
提示:鉴于对MapReduce函数的设计,Reduce必须等待所有相关Map进程返回才能开始启动.所以合理的配置Map-Reduce节点是关键,避免时间冗余,最小化等待时间,是M/R 架构师能力的重要体现
开始----
% 代码来自phofs.erl 模块. phofs is short for Parrallel Highrt-Order Function.
-module(phofs).
-export([mapreduce/4]).
-import(lists, [foreach/2]).
%% F1(Pid, X) -> sends {Key,Val} messages to Pid
%% F2(Key, [Val], AccIn) -> AccOut
mapreduce(F1, F2, Acc0, L) ->
S = self(),
Pid = spawn(fun() -> run(S, F1, F2, Acc0, L) end),
receive
{Pid, Result} ->
Result
end.
% 本段代码的主函数 mapreduce由4个参数组成.
% F1 - Map函数
% F2 - Reduce函数
% Acc0 - 累加器的初始值, 函数最后会返回Acc0的最后累加结果
% L - 运算数据,装载在一个序列中.
run(Parent, F1, F2, Acc0, L) ->
process_flag(trap_exit, true),
ReducePid = self(),
%% 启动 Map运算
%% 对 序列L 中的每一个单元e 进行F1(e)运算. 并为每个单元创建一个进程
%% 此步是ERLANG优势的最大体现.最大化计算性能
foreach(fun(X) ->
spawn_link(fun() -> do_job(ReducePid, F1, X) end)
end, L),
% 获得 序列L 的元素量N.也就是总进程数N,并等待来自N个进程的结果,存到Dict0.
N = length(L),
Dict0 = dict:new(),
Dict1 = collect_replies(N, Dict0),
%% 启动Reduce运算,F2 代表某种Reduce 法则.用户可以自己选择并归的方案.
%% 对Dict1 哈希序列的key-value元素e 运行F2(e)并返回Acc0的累加器.
%% dict:fold函数我研究了好久,后来不断的查看文档,搜结果,讨论(可能本身愚钝:P), 其相当于lists:foldr
%% 也就是相当于python的reduce函数 e.g: reduce(lambda x,y:x+y,range(5)) ===> 1+2+3+4+5.运算集合来自Dict1,运算法则来自F2.
Acc = dict:fold(F2, Acc0, Dict1),
%% 最后把结果返回主函数mapreduce. 并打印.
Parent ! {self(), Acc}.
%% collect_replies 函数 负责处理Map进程的返回结果.并存入某个容器(这里用的是进程字典,同样,Ets,Dts都是可选容器)
%% 当某个Map 任务完成,会自动结束起进程proc,并发送'EXIT',这时候collect_replies会把这个proc 从等待进程序列删除.
>%% 当N=0时,所有map任务完毕,就会把所有相同key值的元素整合到同一个序列中作为新value,并重新对应相应的key.
%% 最后形成一个完整的 key-value Hash Table, 并返回到上面的 Dict1.
collect_replies(0, Dict) ->
Dict;
collect_replies(N, Dict) ->
receive
{Key, Val} ->
case dict:is_key(Key, Dict) of
true ->
Dict1 = dict:append(Key, Val, Dict),
collect_replies(N, Dict1);
false ->
Dict1 = dict:store(Key,[Val], Dict),
collect_replies(N, Dict1)
end;
{'EXIT', _, _} ->
collect_replies(N-1, Dict)
end.
%% Call F(Pid, X)
%% F must send {Key, Value} messsages to Pid
%% and then terminate
do_job(ReducePid, F, X) ->
F(ReducePid, X).
-----完
提示:鉴于对MapReduce函数的设计,Reduce必须等待所有相关Map进程返回才能开始启动.所以合理的配置Map-Reduce节点是关键,避免时间冗余,最小化等待时间,是M/R 架构师能力的重要体现
Wednesday, December 3, 2008
[原创]搜索引擎分词算法
最近在写www.bitok.cn的时候,一直在想方设法的优化搜索引擎的人工智能程度. 主要在中文分词上,自动分析用户的想法.
1 .比如有朋友搜索 "北京 大学". 那么SE(以后简称代替搜索引擎) 会根据 空格 把 关键字 分成 "北京"和"大学".
2. 但是如果把 空格去掉,输入 "北京大学". 那么就是一个不同的结果,精确搜索结果.
但如果要保证最大模糊度+最高精确度,这个就是难度了.
举个例子,我输入"北京大学", 我希望把 直接匹配的 "北京大学"(参见2的搜索结果) 排在前面,同时兼顾"北京" "大学"的分词,把相应模糊结果跟着搜索出来. 这个就是难点了.
参考了google算法之美. 我发现了一些方法. 比如某个关键词 "发展中国家" .
他主要的分词归类是 1."发展中"+"国家", 2. "发展"+"中国"+"家"
最普遍的方法是,根据词库,把1,2 的组合 带入到 词库(这里我们先忽略词库本身的不确定因素)中,去判断1和2所出现的概率, 最高的为最优.
-----------
但是最近闲看空气动力学的计算力学分析,其方法就是把力学问题的数学模型进行尽可能小粒度的微分,然后分析后综合.
所以我想到一个方法,就是把关键词(比如 "发展中国家" )全部按 字 来分开,比如 "发"+"展"+"中"+"国"+"家",
代入到搜索SE中用搜索,结果为 QuerySet0.
然后重新组成序列:
------------ "发展"+"展中"+"中国"+"国家"+"发展中"+"展中国"+"中国家"+"发展中国"+"展中国家".
然后带入到词库中. 假设词库足够的常用词汇统计,那么他就会把序列缩减为:
------------ "发展"+"中国"+"国家"+"发展中".
这时候再对QuerySet0分别对以上4个词进行查询,得出Query1,Query2,Query3,Query4.(每个集合中肯定有结果是重复的)
然后把Query1~4 进行整合.统计出每个结果被重复的次数.其中重复次率最高的分词结果则是最优分词结果.
(完)
1 .比如有朋友搜索 "北京 大学". 那么SE(以后简称代替搜索引擎) 会根据 空格 把 关键字 分成 "北京"和"大学".
2. 但是如果把 空格去掉,输入 "北京大学". 那么就是一个不同的结果,精确搜索结果.
但如果要保证最大模糊度+最高精确度,这个就是难度了.
举个例子,我输入"北京大学", 我希望把 直接匹配的 "北京大学"(参见2的搜索结果) 排在前面,同时兼顾"北京" "大学"的分词,把相应模糊结果跟着搜索出来. 这个就是难点了.
参考了google算法之美. 我发现了一些方法. 比如某个关键词 "发展中国家" .
他主要的分词归类是 1."发展中"+"国家", 2. "发展"+"中国"+"家"
最普遍的方法是,根据词库,把1,2 的组合 带入到 词库(这里我们先忽略词库本身的不确定因素)中,去判断1和2所出现的概率, 最高的为最优.
-----------
但是最近闲看空气动力学的计算力学分析,其方法就是把力学问题的数学模型进行尽可能小粒度的微分,然后分析后综合.
所以我想到一个方法,就是把关键词(比如 "发展中国家" )全部按 字 来分开,比如 "发"+"展"+"中"+"国"+"家",
代入到搜索SE中用搜索,结果为 QuerySet0.
然后重新组成序列:
------------ "发展"+"展中"+"中国"+"国家"+"发展中"+"展中国"+"中国家"+"发展中国"+"展中国家".
然后带入到词库中. 假设词库足够的常用词汇统计,那么他就会把序列缩减为:
------------ "发展"+"中国"+"国家"+"发展中".
这时候再对QuerySet0分别对以上4个词进行查询,得出Query1,Query2,Query3,Query4.(每个集合中肯定有结果是重复的)
然后把Query1~4 进行整合.统计出每个结果被重复的次数.其中重复次率最高的分词结果则是最优分词结果.
(完)
Monday, December 1, 2008
django WEEKDAYS_ABBR 错误解决方案
最近在用django写学校的搜索导航.结果在ADMIN 页面 遇到了 WEEKDAYS_ABBR 未定义的情况.
这个问题是 django 0.96到1.0的 BUG. 在最新的django trunk版本就已经fix了. 所以遇到这种情况下,最彻底的方法就是重新安装最新django.
而学校最近在封外网代理. 所以我干脆直接COPY了 WEEKDAYS_ABBR .
在 django.utils.dates 中 添加:
WEEKDAYS_ABBR = {0:_('Mon'), 1:_('Tue'), 2:_('Wed'), 3:_('Thu'), 4:_('Fri'),5:_('Sat'), 6:_('Sun')}
Problem resolved.
这个问题是 django 0.96到1.0的 BUG. 在最新的django trunk版本就已经fix了. 所以遇到这种情况下,最彻底的方法就是重新安装最新django.
而学校最近在封外网代理. 所以我干脆直接COPY了 WEEKDAYS_ABBR .
在 django.utils.dates 中 添加:
WEEKDAYS_ABBR = {0:_('Mon'), 1:_('Tue'), 2:_('Wed'), 3:_('Thu'), 4:_('Fri'),5:_('Sat'), 6:_('Sun')}
Problem resolved.
linux matlab 2008 中文支持解决
操作系统:ubuntu 8.04
matlab版本:r2008b
matlab的GUI是用JAVA完成的。 所以基于matlab的中文问题的实质就是java环境的解决。
0.安装最新java环境 sun-java6-jre
1.复制其文件夹/usr/jvm/sun...到 $MATLABPATH/sys/java/jre/glnx86/ 并改名为jre
2.cd 进 $MATLABPATH/sys/java/jre/glnx86/jre/lib/fonts/ ,并makedir fallback
3.把 windows系统中的 WINDOWS/Fonts/simsun.ttc 复制到 fallback中
4.cd fallback && mkfontscale
5. cd .. && cat fallback/fonts.scale >> fonts.dir && chmod 666 fonts.dir
6. chmod 766 fallback/*
matlab版本:r2008b
matlab的GUI是用JAVA完成的。 所以基于matlab的中文问题的实质就是java环境的解决。
0.安装最新java环境 sun-java6-jre
1.复制其文件夹/usr/jvm/sun...到 $MATLABPATH/sys/java/jre/glnx86/ 并改名为jre
2.cd 进 $MATLABPATH/sys/java/jre/glnx86/jre/lib/fonts/ ,并makedir fallback
3.把 windows系统中的 WINDOWS/Fonts/simsun.ttc 复制到 fallback中
4.cd fallback && mkfontscale
5. cd .. && cat fallback/fonts.scale >> fonts.dir && chmod 666 fonts.dir
6. chmod 766 fallback/*
Subscribe to:
Posts (Atom)