erlang启动参数有3种:emulator flags, flags 和plain arguments。
emulator flags 是以“+”开头的,用来控制模拟器的行为,附送一个非常实用的例子:
相关阅读:http://www.linuxidc.com/Linux/2011-07/39156.htm
- C:>erl +V
- Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 5.8.2
flags 是以“-”开头的, 是erlang运行时系统的参数,可以用init:get_argument/1获得。
plain arguments 普通参数,在第一个flag参数前,或在-- flag之后,-extra后的参数都是普通参数。
- </pre><p><span class="bold_code">erl +W w -sname arnie +R 9 -s my_init -extra +bertie</span></p><p><strong></strong> </p><pre class="plain" name="code">% erl +W w -sname arnie +R 9 -s my_init -extra +bertie
- (arnie@host)1> init:get_argument(sname).
- {ok,[["arnie"]]}
- (arnie@host)2> init:get_plain_arguments().
- ["+bertie"]
Here +W w and +R 9 are emulator flags. -s my_init is an init flag, interpreted by init. -sname arnie is a user flag, stored by init. It is read by Kernel and will cause the Erlang runtime system to become distributed. Finally, everything after -extra (that is, +bertie) is considered as plain arguments.
Flags
-Application Par Val 把应用中的Par参数设置为值Val;
-args_file FileName 从文件FileName读取命令行参数;
-boot File 指定启动使用的boot文件,默认是$ROOT/bin/start.boot,在这个目录下还有start_clean.boot,start_sasl.boot。如果需要sasl的话,就“-boot start_sasl ”;
-boot_var Var Dir 代替$ROOT用的;
-code_path_cache 不常用;
-compile Mod1 Mod2 ... 不推荐使用了,应该使用erlc;
-config Config 指定配置文件,这个是很有用的,比如在Programming Erlang里,就用到 erl -boot start_sasl -config elog3,其中文件全名是elog3.config,内容如下:
- %% rotating log and minimal tty
- [{sasl,[
- {sasl_error_logger,false},
- %%define the parameters of the rotating log
- %%the log file directory
- {error_logger_mf_dir,"D:/erlang/otpexample/error_logs"},
- %% # bytes per log file
- {error_logger_mf_maxbytes,10485760}, %10 MB
- %%maximum number of logfiles
- {error_logger_mf_maxfiles,10}
- ]}].
配置的含义,请参考相关书籍;
-connect_all false 貌似不常用;
-cookie Cookie 被-setcookie代替了;
-detached 脱离console,跑后台erlang进程用的,看做"nohup **** &";
-emu_args debug用的,打印出实际传给模拟器的值;
-env Variable Value 设置操作系统环境变量用的,比如:
- erl -env DISPLAY gin:0
-eval Expr(init flag) 表达式做启动参数,比如(下列代码在本机执行出错,以后再研究):
- % erl -eval '{X,Y,Z}' = now(), random:seed(X,Y,Z).'
-extra(init flag) 后面跟的都是普通参数; -heart 启动心跳监控器;-hidden 设置为隐藏节点,该节点会连接集群的所有节点,但是在其他节点执行node/0,不会列出它;-hosts Hosts erlang运行在那些服务器的IP地址;
-id Id 给erlang进程设置一个id,一般和-sname 和 -name一起用;
-init_debug 在启动/初始化erlang进程时,打印debug信息;-instr-loader Loader 为erl_prim_loader指定装载模块的方法,相当于java里指定classloader;-make-man Module-mode interactive | embedded-name Name 给一个erlang节点/进程设置一个名称-noinput-noshell-nostick
-pa Dir1 Dir2 ...
-pz Dir1 Dir2 ...-remsh Node 远程启动一个erlang节点,比如(当然RSA神马的,要先搞定):
- erl -sname node1 -remsh node2@machine2.example.com
-rsh Program 远程启动一个slave erlang节点,这里 http://www.linuxidc.com/Linux/2011-07/39157p3.htm 有一个例子;
-run Mod [Func [Arg1, Arg2, ...]]
-s Mod [Func [Arg1, Arg2, ...]]
-setcookie Cookie 给节点设置cookie,比如:
- erl -setcookie SFEWRG34AFDSGAFG35235 -name nodex
并且它是运行时可以改的:
- erlang:set_cookie(node(), 'SFEWRG34AFDSGAFG35235').
-shutdown_time Time 关闭节点需要的时间,如果超过,就直接kill,默认是infinity;
-sname Name 给节点设置名字,和-name类似,不过它的结果是:Name@Host ;
-smp [enable|auto|disable] 是否需要支持smp,默认应该是enable的,smp的好处见这里http://www.linuxidc.com/Linux/2011-07/39157p2.htm;
-version(emulator flag)
+a size 一般实用默认值就可以了。
Suggested stack size, in kilowords, for threads in the async-thread pool. Valid range is 16-8192 kilowords. The default suggested stack size is 16 kilowords, i.e, 64 kilobyte on 32-bit architectures. This small default size has been chosen since the amount of async-threads might be quite large. The default size is enough for drivers delivered with Erlang/OTP, but might not be sufficiently large for other dynamically linked in drivers that use thedriver_async() functionality. Note that the value passed is only a suggestion, and it might even be ignored on some platforms.
+A size 一步线程池的大小,默认是0;比如执行werl +A 1,会看到:
- Erlang R14B01 (erts-5.8.2) [smp:2:2] [rq:2] [async-threads:1]
- Eshell V5.8.2 (abort with ^G)
+B [c | d | i]
+c
+d 默认情况下erlang进程遇到内部错误,比如oom,会产生一个crash dump和core dump,+d让节点只产生后者;
+e Number ETS表的最大数量;+ec强制ETS表启动压缩,一般不用的;+fnl 如果文件名使用了ISO-latin-1编码;+fnu如果文件名使用了UTF-8 编码;
+fna 和当前操作系统一致;
+hms Size 指定erlang进程的默认(最小?)堆内存大小(这个应该不用太担心);+hmbs Size 进程默认二进制虚拟内存堆大小;
+K true | false 是否开启kernel poll,就是epoll;
+l+MFlag Value
+P Number erlang节点系统的最大并发进程数;
+R ReleaseNumber
+r
+rg ReaderGroupsLimit Limits the amount of reader groups used by read/write locks optimized for read operations in the Erlang runtime system. By default the reader groups limit equals 8.
+S Schedulers:SchedulerOnline
+sFlag Value
+t size
+T Level
+V 模拟器版本号
+v verbose
+W w | i
+zFlag Value
ERL_CRASH_DUMP
ERL_CRASH_DUMP_NICE
ERL_CRASH_DUMP_SECONDS
ERL_AFLAGS
ERL_ZFLAGS 和 ERL_FLAGS
ERL_LIBS
ERL_EPMD_PORT
关于Erlang和SMP的一些说明
by.Kenneth Erlang/OTP team, Ericsson
译:ShiningRay
以下是一些Erlang SMP实现的细节和与性能与伸缩性相关一些简单介绍。
几周之内还有有一个关于多核如何运作以及未来如何发展的更详细的介绍。我打算将一些内容放在我的报告中,将于9月27日的ICFP2008,Erlang Workshop在Victoria BC展示给大家。
没有SMP支持的Erlang VM只有1个运行在主处理线程中的调度器。该调度器从运行队列(run-queue)中取出可以运行的Erlang进程以及IO任务,而且因为只有一个线程访问他们所以无须锁定任何数据。
而带有SMP支持的Erlang VM可以有一个或多个调度器,每个运行在一个线程中。调度器从同一个公共运行队列中取出可运行的Erlang进程和IO任务。在SMP VM中所有的共享数据结构都会由锁进行保护,运行队列就是这样一个由锁保护的数据结构。
从OTP R12B开始,如果操作系统报告有多于1个的CPU(或者核心)VM的SMP版本会自动启动,并且根据CPU或者核心的数量启动同样数量的调度器。
你可以从“erl”命令打印出来的第一行看到它选择了哪些参数。例如:
Erlang (BEAM) emulator version 5.6.4 [source] [smp:4] [asynch-threads:0] …..
其中“[smp:4]”表示SMP VM运行了4个调度器。
默认值可以用“-smp [enable|disable|auto]”来替换,auto是默认的。如果smp被启用了(-smp enable),要设置调度器的数量可以使用“+S Number”其中Number是调度器的数量(1到1024)
注意1:运行多于CPU或核心总数的调度器不会有任何提升。
注意2:在某些操作系统中一个进程可使用的CPU或者核心的数量可以被限制。例如,在Linux中,命令“taskset”就可以实现这个功能。Erlang VM目前还只能探测CPU或者核心的总数,不会考虑“taskset”所设置的掩码。正因如此,例如可能会出现(已经出现过了)即使Erlang VM运行了4个调度器,也只使用了2个核心。OS会进行限制因为它要考虑“taskset”所设置的掩码。
每个Erlang VM的调度器都运行于一个OS线程上,是OS来决定线程是否执行在不同的核心上。一般来说OS会很好地处理这个问题并且会保证线程在执行期间运行于同一个核心上。
Erlang进程会被不同的调度器运行,因为他们是从一个公共运行队列中被取出,由首先可用的调度器运行。
只有一个调度器的SMP VM要比非SMP的VM稍微慢那么一点点。SMP VM内部需要用到各种锁,不过只要不存在锁的争用,那么由锁引起的开销不会非常大(就是锁争用上面需要花时间)。这也解释了为何在某些情况下,运行多个只有一个调度器的SMP VM要比包含多个调度器的单一SMP VM更加高效。当然运行多个VM要求应用可以按照多个并行任务的方式运行并且之间没有或者几乎不通讯。
一个程序是否能在多核上的SMP VM中良好地进行提升很大程度上取决于程序的性质,某些程序可以保持线性提升至8核甚至16核,同时其他某些程序基本不能提升,连2核都不行。实际应用中很多程序都能在主流市场的核心数上得到提升,见下文。
若并行的持续“通话”由每个核心一个或多个Erlang进程来表示,实际的支持大量通话的电信产品已经先现出在双核和四核处理器上不俗的伸缩性。注意,这些产品是在SMP VM和多核处理器出现很久以前按照普通的Erlang风格来写的,他们也能无须任何修改甚至不需重新编译代码就能从Erlang SMP VM中获益。
SMP实现正被不断改进以便能得到更好的性能和伸缩性。在每个服务发布版R12B-1,2,3,4,5…,R13B等等中,你都能发现新的优化。
单一的常见运行队列随着CPU或核心的数量的增加会成为一个显著的瓶颈。
这从4核开始往上就会显现出来,不过4核仍然可以为多数应用程序提供不错的性能。我们正在从事一个每个调度器一个运行队列的解决方法作为目前最重要的改进。
Ets表格会引入锁。在R12B-4之前在每次对一个ets-table的访问中会用到两个锁,但是在R12B-4中meta-table的锁被优化过,可以显著减少争用(前面已经提到争用是有很大代价的)。如果很多Erlang进程访问同一个表格,就会有很多锁争用造成性能降低尤其当这些进程主要工作是访问ets-table。锁存在于表级而非记录级。注意!这也会影响到Mnesia因为Mnesia用到了很多ets-table。
当我们开始实现SMP VM的最初,我们就确定了策略:“首先让它可以运行,然后测量,然后优化”。自从2006年五月我们发布了第一个稳定的SMP VM(R11B)以来,我们一直遵循着这个策略。
还有更多已知的东西可以改进,我们会按照性能的收益大小先后各个击破。
我们将主要的精力放在多核(大于4)上更好的连续伸缩性上。
即使SMP系统有还有一些已知的瓶颈不过已经有不错的整体性能和伸缩性,同时我相信在让程序员利用多核机器事半功倍方面,我们是一个卓越的典范。
Erlang集群节点集合的启动
一、配置SSH客户端:无需密码的连接
1. SSH客户端RSA key授权
i). 生成SSH RSA key:
ssh-keygen -t rsa
全回车取缺省,将在~/.ssh目录下将生成id_rsa和id_rsa.pub俩文件
ii) 将生产的公共RSA key拷贝到目标机器上:
a).将id_rsa.pub文件拷贝到目标机器上:
scp ~/.ssh/id_rsa.pub userid@ssh2_server:id_rsa.pub
b). ssh登陆目标机器,在目标机器的~/.ssh目录下生成文件内容:
cat id_rsa.pub >>$HOME/.ssh/authorized_keys
删掉id_rsa.pub
以上两步命令可以用一条命令实现:
ssh-copy-id ssh2-server
本质上都是把master上生成的id_rsa.pub文件拷贝到slave机器./ssh目录下,同时改名为authorized_keys
这一步完成后,从master机器上登录slave机器直接
ssh slave
就行了,不用输入密码。
同样的,slave到master也得这样:不用输入密码直接ssh
集群内所有的机器相互之间都要这样实现无密码输入就能直接ssh
2. 在启动master节点的那个机器上,启动SSH-agent软件并添加你的用户ID
这样每次连接时就不需要passphrase了,办法是让ssh-agent记住你
i) 首先确认你的机器上有ssh-agent在运行(一般都没有)
ps aux|grep ssh-agent
查看ssh-agent运行在当前窗口管理器(或者shell)下
pstree
如果不是,在shell中创建一个ssh-agent会话:
ssh-agent screen
这回启动了一个带ssh-agent的screen会话窗口,以后这个screen控制台内的所有命令都要经过ssh-agent
ii) 添加你的ID
ssh-add
你可以查看当前ssh-agent中已添加的ID
ssh-add -l
也可以删除一个ID
ssh-add -d
3. 集群的路由进出
当建立集群后,经常需要访问作为网关(或者负载均衡器)的前端计算机。要访问其它节点,你需要告诉作为网管的机器将你的请求路由到机器节点中。
例如,假设你的网关是80.65.232.137。控制用的计算机在集群之外,这个机器是操作员用于控制集群的计算机。集群内部网络是192.0.0.0。在你的客户计算机上,启动命令:
route add -net 192.0.0.0 gw 80.65.232.137 netmask 255.255.255.0
这个命令需要确保网关计算机上IP forwarding 可用
要确保正确的路由,可以维护一个常用的/etc/hosts文件,该文件中记录了你的集群中的所有计算机,例子中,集群有7台计算机组成.
10.9.195.12 controler
80.65.232.137 gateway
192.0.0.11 eddieware
192.0.0.21 yaws1
192.0.0.22 yaws2
192.0.0.31 mnesia1
192.0.0.32 mnesia2
也可以设置DNS服务器,但对小网络来说/etc/hosts文件就已经足够了
二、启动Erlang master节点并建立Erlang集群
一旦通过SSH连接集群不再提示输入密码后建立一个Erlang集群将变得非常容易。
1. 启动Erlang master节点的模块:
- -module(cluster).
- -export([slaves/1]).
- %% Argument:
- %% Hosts: List of hostname (string)
- slaves([]) ->
- ok;
- slaves([Host|Hosts]) ->
- Args = erl_system_args(),
- NodeName = "cluster",
- {ok, Node} = slave:start_link(Host, NodeName, Args),
- io:format("Erlang node started = [~p]~n", [Node]),
- slaves(Hosts).
- erl_system_args()->
- Shared = case init:get_argument(shared) of
- error -> " ";
- {ok,[[]]} -> " -shared "
- end,
- lists:append(["-rsh ssh -setcookie ",
- atom_to_list(erlang:get_cookie()),
- Shared, " +Mea r10b "]).
- %% Do not forget to start erlang with a command like:
- %% erl -rsh ssh -sname clustmaster
启动master
- mremond@controler:~/cvs/cluster$ erl -rsh ssh -sname demo
- Erlang (BEAM) emulator version 5.3 [source] [hipe]
- Eshell V5.3 (abort with ^G)
- (demo@controler)1> cluster:slaves(["gateway", "yaws1", "yaws2", "mnesia1", "mnesia2", "eddieware"]).
- Erlang node started = [cluster@gateway]
- Erlang node started = [cluster@yaws1]
- Erlang node started = [cluster@yaws2]
- Erlang node started = [cluster@mnesia1]
- Erlang node started = [cluster@mnesia2]
- Erlang node started = [cluster@eddieware]
- ok
这里的要点是:集群间所有节点(至少是master对所有slave节点)之间都要能实现“相互”无密码输入的ssh登录
我想无密码输入的原理可能是:
机器A生成RSA key,有一个公开的密钥,别的机器B要想无密码ssh这同机器,B必须在本地拥有A的公开密钥