Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 如何计算Erlang中函数调用的数量?_Function_Indexing_Erlang_Counter - Fatal编程技术网

Function 如何计算Erlang中函数调用的数量?

Function 如何计算Erlang中函数调用的数量?,function,indexing,erlang,counter,Function,Indexing,Erlang,Counter,我在Erlang服务器上有一个函数,用于将数据发布到web服务。此web服务需要计数器(调用次数)。我真的不知道他们为什么需要它,但这是至关重要的 由于某些原因,我无法使用外部数据库。所以我需要在服务器上永久存储一些全局变量。我考虑将计数器保存到一个文件中,每次调用函数时提取并递增计数器 有没有更有效的方法来实现我的目标 编辑 该函数可能同时从多个不同的客户机调用,因此这增加了另一个问题:如果3个客户机同时调用该函数,该函数只会增加计数器一次,我将得到一个错误。如何使函数等待另一个函数完成,然后

我在Erlang服务器上有一个函数,用于将数据发布到web服务。此web服务需要计数器(调用次数)。我真的不知道他们为什么需要它,但这是至关重要的

由于某些原因,我无法使用外部数据库。所以我需要在服务器上永久存储一些全局变量。我考虑将计数器保存到一个文件中,每次调用函数时提取并递增计数器

有没有更有效的方法来实现我的目标

编辑 该函数可能同时从多个不同的客户机调用,因此这增加了另一个问题:如果3个客户机同时调用该函数,该函数只会增加计数器一次,我将得到一个错误。如何使函数等待另一个函数完成,然后执行

提前谢谢

如果3个客户端同时调用该函数,该函数将只增加计数器一次,我将得到一个错误。如何使函数等待另一个函数完成,然后执行

我会使用一个由gen_server构建的简单计数器,只从它访问磁盘上的计数器。这样使用
gen_服务器
将确保您永远不会遇到文件访问竞争条件

以下是一些让您开始学习的内容:

-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(文件计数器)。
{好的,文件\计数器}
2> 文件\计数器:启动\链接()。
{好的,}
3> 文件\u计数器:增量()。
0
4> 文件\u计数器:增量()。
1.
5> 文件\u计数器:增量()。
2.
6> [spawn_链接(文件_计数器,增量,[])| |文件_计数器:增量()。
10001
每次调用之前只需调用
file\u counter:increment()
,并使用它返回的值作为计数

编辑:这只是我编写的一个快速模块。您可能应该通过将文件名传递到
start
start\u link
、和
init
,来配置文件名,并且如果您希望能够运行计数器的多个副本,则不使用名称注册进程。这里的代码实际上是一个POC,可以让您开始


(在带有SSD磁盘的系统上,我能够每秒执行大约5000次
file\u counter:increment()

更有效的方法是在启动时读取计数器并将其存储在ETS(或有状态进程)中,然后在关机时将其写回。但是:这不是100%可靠。如果“忘记”会发生什么关于多个调用,并尝试使用较早的号码调用?web服务将返回某种错误,并且以下调用将毫无意义。这就是为什么保持计数器正确非常重要的原因。函数是否会被并发调用(从>1个Erlang进程)?在这种情况下,将数据存储在文件中可能会导致竞争情况。@Dogbert请查看编辑。谢谢您的回答。我对Erlang非常陌生,在阅读有关gen:server的文档之前,它是否会保存计数器以防服务器崩溃或断电?我发布的代码将在每次调用
increme之前将计数器写入文件nt
返回。如果您的程序在
增量
返回之后,在您发出web服务请求之前崩溃/断电,则计数器不会回滚,否。
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