From c1ef1accecaadf90e91fc6bd7179b5762a9c146e Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Mon, 5 May 2025 22:24:23 +0800 Subject: [PATCH] fix micro service --- apps/efka/src/efka_micro_service.erl | 119 +++++++-------------------- 1 file changed, 29 insertions(+), 90 deletions(-) diff --git a/apps/efka/src/efka_micro_service.erl b/apps/efka/src/efka_micro_service.erl index 462f288..e2d811a 100644 --- a/apps/efka/src/efka_micro_service.erl +++ b/apps/efka/src/efka_micro_service.erl @@ -94,14 +94,12 @@ init([Service = #micro_service{service_id = ServiceId, work_dir = WorkDir0, stat case file:read_file(WorkDir ++ "manifest.json") of {ok, ManifestInfo} -> Manifest = jiffy:decode(ManifestInfo, [return_maps]), - lager:debug("main: ~p", [Manifest]), case check_manifest(Manifest) of ok -> %% 数据的状态和运行状态是2回事 case Status == 1 of true -> - StartCmd = maps:get(<<"start">>, Manifest), - case boot_service(WorkDir0, StartCmd) of + case boot_service(WorkDir0, Manifest) of {ok, Port} -> {os_pid, OSPid} = erlang:port_info(Port, os_pid), lager:debug("[efka_micro_service] service: ~p, port: ~p, boot_service success os_pid: ~p", [ServiceId, Port, OSPid]), @@ -150,8 +148,7 @@ handle_call(start_service, _From, State = #state{running_status = ?STATUS_RUNNIN {reply, {error, <<"service is running">>}, State}; handle_call(start_service, _From, State = #state{running_status = ?STATUS_STOPPED, manifest = Manifest, service = Service = #micro_service{work_dir = WorkDir0, service_id = ServiceId}}) -> %% 异步启动服务 - StartCmd = maps:get(<<"start">>, Manifest), - case boot_service(WorkDir0, StartCmd) of + case boot_service(WorkDir0, Manifest) of {ok, Port} -> %% 更新数据库状态 micro_service_model:start_service(ServiceId), @@ -168,20 +165,12 @@ handle_call(stop_service, _From, State = #state{running_status = ?STATUS_STOPPED lager:debug("stop service port: ~p, os_pid: ~p", [Port, OSPid]), {reply, {error, <<"service not running">>}, State}; -handle_call(stop_service, _From, State = #state{running_status = ?STATUS_RUNNING, port = Port, os_pid = OSPid, manifest = Manifest, - service = Service = #micro_service{service_id = ServiceId, work_dir = WorkDir0}}) when is_port(Port) -> - +handle_call(stop_service, _From, State = #state{running_status = ?STATUS_RUNNING, port = Port, os_pid = OSPid, service = Service = #micro_service{service_id = ServiceId}}) when is_port(Port) -> %% 优先使用微服务提供的stop指令, 没有提供的情况下,使用kill指令 - case maps:find(<<"stop">>, Manifest) of - error -> - kill_os_pid(OSPid); - {ok, StopCmd} -> - kill_service(WorkDir0, StopCmd, OSPid) - end, + kill_os_pid(OSPid), micro_service_model:stop_service(ServiceId), erlang:is_port(Port) andalso erlang:port_close(Port), - lager:debug("port: ~p, os_pid: ~p, will closed", [Port, OSPid]), {reply, ok, State#state{port = undefined, os_pid = undefined, running_status = ?STATUS_STOPPED, service = Service#micro_service{status = 0}}}; @@ -209,8 +198,7 @@ handle_info({timeout, _, reboot_service}, State = #state{service = #micro_servic lager:debug("[efka_micro_service] service_id: ~p, is stopped, ignore boot_service", [ServiceId]), {noreply, State}; handle_info({timeout, _, reboot_service}, State = #state{manifest = Manifest, service = #micro_service{work_dir = WorkDir0, service_id = ServiceId, status = 1}}) -> - StartCmd = maps:get(<<"start">>, Manifest), - case boot_service(WorkDir0, StartCmd) of + case boot_service(WorkDir0, Manifest) of {ok, Port} -> {os_pid, OSPid} = erlang:port_info(Port, os_pid), lager:debug("[efka_micro_service] reboot service success: ~p, port: ~p, os_pid: ~p", [ServiceId, Port, OSPid]), @@ -262,7 +250,7 @@ code_change(_OldVsn, State = #state{}, _Extra) -> %% 检查配置是否合法 -spec check_manifest(Manifest :: map()) -> ok | {error, Reason :: binary()}. check_manifest(Manifest) when is_map(Manifest) -> - RequiredKeys = [<<"serivce_id">>, <<"start">>, <<"health_check">>, <<"stop">>], + RequiredKeys = [<<"serivce_id">>, <<"exec">>, <<"args">>, <<"health_check">>], check_manifest0(RequiredKeys, Manifest). check_manifest0([], _Manifest) -> @@ -290,8 +278,8 @@ check_manifest0([<<"health_check">>|T], Manifest) -> {ok, _} -> {error, <<"health_check is not string">>} end; -check_manifest0([<<"start">>|T], Manifest) -> - case maps:find(<<"start">>, Manifest) of +check_manifest0([<<"exec">>|T], Manifest) -> + case maps:find(<<"exec">>, Manifest) of error -> {error, <<"miss start">>}; {ok, Cmd} when is_binary(Cmd) -> @@ -301,42 +289,17 @@ check_manifest0([<<"start">>|T], Manifest) -> check_manifest0(T, Manifest); _ -> {error, <<"start cmd cannot contain args">>} - end; - %% 对参数项目不进行检查 - {ok, [Cmd|_Args]} when is_binary(Cmd) -> - %% 不能包含空格 - case binary:match(Cmd, <<" ">>) of - nomatch -> - check_manifest0(T, Manifest); - _ -> - {error, <<"start cmd cannot contain args">>} - end; - {ok, _} -> - {error, <<"start is not string">>} + end end; -check_manifest0([<<"stop">>|T], Manifest) -> - case maps:find(<<"stop">>, Manifest) of +check_manifest0([<<"args">>|T], Manifest) -> + case maps:find(<<"args">>, Manifest) of error -> check_manifest0(T, Manifest); - {ok, Cmd} when is_binary(Cmd) -> - %% 不能包含空格 - case binary:match(Cmd, <<" ">>) of - nomatch -> - check_manifest0(T, Manifest); - _ -> - {error, <<"stop cmd cannot contain args">>} - end; %% 对参数项目不进行检查 - {ok, [Cmd|_Args]} when is_binary(Cmd) -> - %% 不能包含空格 - case binary:match(Cmd, <<" ">>) of - nomatch -> - check_manifest0(T, Manifest); - _ -> - {error, <<"stop cmd cannot contain args">>} - end; + {ok, Args} when is_list(Args) -> + check_manifest0(T, Manifest); {ok, _} -> - {error, <<"stop is not string">>} + {error, <<"args must be list">>} end. %% 关闭系统进程 @@ -348,24 +311,21 @@ kill_os_pid(OSPid) when is_integer(OSPid) -> lager:debug("kill cmd is: ~p", [Cmd]), os:cmd(Cmd). -%% 执行命令 --spec kill_service(WorkDir0 :: binary(), ExecCmd0 :: binary() | [binary()], OSPid :: integer()) -> no_return(). -kill_service(WorkDir0, ExecCmd0, OSPid) when is_binary(WorkDir0) -> - {RealExecCmd, PortSettings} = make_cmd(WorkDir0, ExecCmd0), - Port = erlang:open_port({spawn_executable, RealExecCmd}, PortSettings), - receive - {Port, {exit_status, Code}} -> - lager:debug("[service] exit with code: ~p", [Code]) - after 5000 -> - erlang:port_close(Port), - kill_os_pid(OSPid) - end, - is_port(Port) andalso erlang:port_close(Port). - %% 启动微服务 --spec boot_service(WorkDir :: binary(), ExecCmd :: binary() | [binary()]) -> {ok, Port :: port()} | {error, Reason :: binary()}. -boot_service(WorkDir0, ExecCmd0) when is_binary(WorkDir0), is_binary(ExecCmd0); is_list(ExecCmd0) -> - {RealExecCmd, PortSettings} = make_cmd(WorkDir0, ExecCmd0), +-spec boot_service(WorkDir :: binary(), Manifest :: map()) -> {ok, Port :: port()} | {error, Reason :: binary()}. +boot_service(WorkDir0, Manifest) when is_binary(WorkDir0), is_map(Manifest) -> + ExecCmd0 = maps:get(<<"exec">>, Manifest), + Args0 = maps:get(<<"args">>, Manifest, []), + + WorkDir = binary_to_list(WorkDir0), + PortSettings = [ + {cd, WorkDir}, + {args, [binary_to_list(A) || A <- Args0]}, + exit_status + ], + ExecCmd = binary_to_list(ExecCmd0), + RealExecCmd = filename:absname_join(WorkDir, ExecCmd), + Port = erlang:open_port({spawn_executable, RealExecCmd}, PortSettings), {ok, Port}. @@ -376,25 +336,4 @@ is_url(Input) when is_binary(Input) -> true catch _:_ -> false - end. - --spec make_cmd(WorkDir0 :: binary(), Cmd0 :: binary() | [binary()]) -> {RealCmd :: string(), PortSettings :: list()}. -make_cmd(WorkDir0, Cmd0) when is_binary(Cmd0) -> - WorkDir = binary_to_list(WorkDir0), - PortSettings = [ - {cd, WorkDir}, - exit_status - ], - ExecCmd = binary_to_list(Cmd0), - RealExecCmd = filename:absname_join(WorkDir, ExecCmd), - {RealExecCmd, PortSettings}; -make_cmd(WorkDir0, [Cmd0|Args]) when is_binary(Cmd0) -> - WorkDir = binary_to_list(WorkDir0), - PortSettings = [ - {cd, WorkDir}, - {args, [binary_to_list(A) || A <- Args]}, - exit_status - ], - ExecCmd = binary_to_list(Cmd0), - RealExecCmd = filename:absname_join(WorkDir, ExecCmd), - {RealExecCmd, PortSettings}. \ No newline at end of file + end. \ No newline at end of file