fix redis_server
This commit is contained in:
parent
be053ef8b4
commit
eb793e913b
108
apps/sdlan/src/policy/maxwell_redis_channel.erl
Normal file
108
apps/sdlan/src/policy/maxwell_redis_channel.erl
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author anlicheng
|
||||||
|
%%% @copyright (C) 2026, <COMPANY>
|
||||||
|
%%% @doc
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 28. 2月 2026 22:07
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(maxwell_redis_channel).
|
||||||
|
-author("licheng5").
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start/1, loop/1]).
|
||||||
|
|
||||||
|
-record(command, {
|
||||||
|
data = <<>>,
|
||||||
|
stage = parse_arg_num,
|
||||||
|
arg_num = 0,
|
||||||
|
args = []
|
||||||
|
}).
|
||||||
|
|
||||||
|
-record(state, {
|
||||||
|
socket,
|
||||||
|
command
|
||||||
|
}).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% esockd callback
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
start(Socket) ->
|
||||||
|
spawn_link(?MODULE, loop, [#state{socket = Socket, command = #command{}}]).
|
||||||
|
|
||||||
|
loop(State=#state{socket = Socket, command = Command = #command{data = Data}}) ->
|
||||||
|
inet:setopts(Socket, [{active, once}]),
|
||||||
|
receive
|
||||||
|
{tcp, _, Packet} ->
|
||||||
|
NData = <<Data/binary, Packet/binary>>,
|
||||||
|
case parse(Command#command{data = NData}) of
|
||||||
|
{ok, #command{args = Args}} ->
|
||||||
|
{reply, Reply} = handle_command(Args),
|
||||||
|
gen_tcp:send(Socket, Reply),
|
||||||
|
loop(State#state{command = #command{}});
|
||||||
|
{more_data, NCommand} ->
|
||||||
|
%% 请求的数据包过大,一次接受不完整
|
||||||
|
loop(State#state{command = NCommand})
|
||||||
|
end;
|
||||||
|
{tcp_error, _} ->
|
||||||
|
exit(normal);
|
||||||
|
{tcp_closed, _} ->
|
||||||
|
exit(normal)
|
||||||
|
end.
|
||||||
|
|
||||||
|
%% 处理请求命令
|
||||||
|
handle_command(Args) ->
|
||||||
|
logger:debug("[maxwell_redis_channel] args: ~p", [Args]),
|
||||||
|
{reply, encode({error, <<"Unsuported Command">>})}.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%% helper methods
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
%% 解析请求的包, 支持请求不在一个包里面的情况, 基于状态机
|
||||||
|
parse(Command = #command{stage = parse_arg_num, data = <<$*, Rest/binary>>}) ->
|
||||||
|
[ArgNum0, ArgBin] = binary:split(Rest, <<$\r, $\n>>),
|
||||||
|
ArgNum = binary_to_integer(ArgNum0),
|
||||||
|
parse(Command#command{arg_num = ArgNum, data = ArgBin, stage = parse_arg});
|
||||||
|
%% 解析请求的参数
|
||||||
|
parse(Command = #command{stage = parse_arg, args = Args, arg_num = 0, data = <<>>}) ->
|
||||||
|
{ok, Command#command{args = lists:reverse(Args)}};
|
||||||
|
parse(Command = #command{stage = parse_arg, args = Args, arg_num = ArgNum, data = ArgBin}) ->
|
||||||
|
case binary:split(ArgBin, <<$\r, $\n>>) of
|
||||||
|
[<<"$", ArgLen0/binary>>, RestArgBin] ->
|
||||||
|
ArgLen = binary_to_integer(ArgLen0),
|
||||||
|
case RestArgBin of
|
||||||
|
<<Arg:ArgLen/binary, $\r, $\n, RestArgBin1/binary>> ->
|
||||||
|
parse(Command#command{arg_num = ArgNum - 1, args = [Arg | Args], data = RestArgBin1});
|
||||||
|
_ ->
|
||||||
|
{more_data, Command}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
{more_data, Command}
|
||||||
|
end.
|
||||||
|
|
||||||
|
%% redis数据返回格式化
|
||||||
|
-spec encode(tuple() | binary() | list()) -> iolist().
|
||||||
|
encode({single_line, Arg}) when is_binary(Arg) ->
|
||||||
|
[<<$+>>, Arg, <<$\r, $\n>>];
|
||||||
|
encode({error, Arg}) when is_binary(Arg) ->
|
||||||
|
[<<$->>, Arg, <<$\r, $\n>>];
|
||||||
|
encode(Arg) when is_integer(Arg) ->
|
||||||
|
[<<$:>>, integer_to_list(Arg), <<$\r, $\n>>];
|
||||||
|
encode(Arg) when is_binary(Arg) ->
|
||||||
|
[<<$$>>, integer_to_list(iolist_size(Arg)), <<$\r, $\n>>, Arg, <<$\r, $\n>>];
|
||||||
|
encode(Args) when is_list(Args) ->
|
||||||
|
ArgCount = [<<$*>>, integer_to_list(length(Args)), <<$\r, $\n>>],
|
||||||
|
ArgsBin = lists:map(fun encode/1, lists:map(fun to_binary/1, Args)),
|
||||||
|
[ArgCount, ArgsBin].
|
||||||
|
|
||||||
|
%% 将数据转换成binary
|
||||||
|
to_binary(X) when is_list(X) ->
|
||||||
|
unicode:characters_to_binary(X);
|
||||||
|
to_binary(X) when is_atom(X) ->
|
||||||
|
list_to_binary(atom_to_list(X));
|
||||||
|
to_binary(X) when is_binary(X) ->
|
||||||
|
X;
|
||||||
|
to_binary(X) when is_integer(X) ->
|
||||||
|
list_to_binary(integer_to_list(X)).
|
||||||
44
apps/sdlan/src/policy/maxwell_redis_server.erl
Normal file
44
apps/sdlan/src/policy/maxwell_redis_server.erl
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author anlicheng
|
||||||
|
%%% @copyright (C) 2026, <COMPANY>
|
||||||
|
%%% @doc
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 28. 2月 2026 22:07
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(maxwell_redis_server).
|
||||||
|
-author("licheng5").
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/1, init/1]).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% esockd callback
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
start_link(Port) when is_integer(Port) ->
|
||||||
|
{ok, spawn_link(?MODULE, init, [Port])}.
|
||||||
|
|
||||||
|
init(Port) ->
|
||||||
|
{ok, LSocket} = gen_tcp:listen(Port, [
|
||||||
|
binary,
|
||||||
|
{packet, 0},
|
||||||
|
{reuseaddr, true},
|
||||||
|
{backlog, 1024},
|
||||||
|
{active, false}
|
||||||
|
]),
|
||||||
|
accept_loop(LSocket).
|
||||||
|
|
||||||
|
accept_loop(LSocket) ->
|
||||||
|
case gen_tcp:accept(LSocket) of
|
||||||
|
{ok, Socket} ->
|
||||||
|
%% 每个连接一个进程
|
||||||
|
Pid = spawn(fun() -> maxwell_redis_channel:start(Socket) end),
|
||||||
|
ok = gen_tcp:controlling_process(Socket, Pid),
|
||||||
|
accept_loop(LSocket);
|
||||||
|
{error, closed} ->
|
||||||
|
exit(tcp_closed);
|
||||||
|
{error, Reason} ->
|
||||||
|
logger:debug("[maxwell_redis_server] Accept error: ~p~n", [Reason]),
|
||||||
|
accept_loop(LSocket)
|
||||||
|
end.
|
||||||
@ -88,6 +88,15 @@ init([]) ->
|
|||||||
shutdown => 2000,
|
shutdown => 2000,
|
||||||
type => worker,
|
type => worker,
|
||||||
modules => ['sdlan_sync_mysql']
|
modules => ['sdlan_sync_mysql']
|
||||||
|
},
|
||||||
|
|
||||||
|
#{
|
||||||
|
id => maxwell_redis_server,
|
||||||
|
start => {maxwell_redis_server, start_link, [16379]},
|
||||||
|
restart => permanent,
|
||||||
|
shutdown => 2000,
|
||||||
|
type => worker,
|
||||||
|
modules => ['maxwell_redis_server']
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user