我的Erlang服务器上有一个功能,该功能将数据发布到Web服务。此Web服务需要计数器(被调用多少次)。我真的不知道他们为什么需要它,但这很关键。
由于某些原因,我无法使用外部数据库。因此,我需要将一些全局变量永久存储在服务器上。我考虑过将计数器保存到文件中,每次调用函数时提取并递增它。
有没有更有效的方法可以实现我的目标?
编辑可能同时从多个不同的客户端调用该函数,因此这又增加了一个问题:如果3个客户端同时调用该函数,则该函数只会将计数器递增一次,而我会得到一个错误。如何使函数等待另一个函数完成然后执行?
提前致谢。
如果3个客户端同时调用该函数,则该函数只会将计数器递增一次,而我会收到错误消息。如何使函数等待另一个函数完成然后执行?
我将使用一个内置的简单计数器,gen_server
并且只能从中访问磁盘上的计数器。这样使用gen_server
将确保您永远不会遇到文件访问争用情况。
以下是一些入门知识:
-module(file_counter).
-export([start_link/0, start/0, increment/0]).
-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
start() ->
gen_server:start({local, ?MODULE}, ?MODULE, [], []).
increment() ->
gen_server:call(?MODULE, increment).
init([]) ->
{ok, "file_counter.txt"}.
handle_call(increment, _From, File) ->
Counter = case file:read_file(File) of
{ok, Binary} -> binary_to_integer(Binary);
{error, enoent} -> 0
end,
ok = file:write_file(File, integer_to_binary(Counter + 1)),
{reply, Counter, File}.
handle_cast(_Req, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
演示:
1> c(file_counter).
{ok,file_counter}
2> file_counter:start_link().
{ok,<0.40.0>}
3> file_counter:increment().
0
4> file_counter:increment().
1
5> file_counter:increment().
2
6> [ spawn_link(file_counter, increment, []) || _ <- lists:seq(1, 9998) ].
[<0.45.0>,<0.46.0>,<0.47.0>,<0.48.0>,<0.49.0>,<0.50.0>,
<0.51.0>,<0.52.0>,<0.53.0>,<0.54.0>,<0.55.0>,<0.56.0>,
<0.57.0>,<0.58.0>,<0.59.0>,<0.60.0>,<0.61.0>,<0.62.0>,
<0.63.0>,<0.64.0>,<0.65.0>,<0.66.0>,<0.67.0>,<0.68.0>,
<0.69.0>,<0.70.0>,<0.71.0>,<0.72.0>,<0.73.0>|...]
7> file_counter:increment().
10001
只需在拨打file_counter:increment()
每个电话之前先进行通话,然后将其返回的值用作计数即可。
编辑:这只是我写的一个快速模块。您可能应该通过将文件名传递给start
,start_link
和来使其可配置,并且init
如果您希望能够运行计数器的多个副本,则不要使用名称注册该进程。这里的代码实际上是一个POC,可以帮助您入门。
(在具有SSD磁盘的系统上,我file_counter:increment()
每秒能够执行约5000次。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句