Standby system handover
Chaitanya Chalasani
chaitanya.chalasani@REDACTED
Fri Jul 7 14:00:38 CEST 2006
Dear Serge,
Thank you very much. This seems to be a very good architecture for highly
availability. I will try the same.
On Friday 07 July 2006 17:20, Serge Aleynikov wrote:
> Chaitanya,
>
> Wouldn't your packet forwarder be a single point of failure then?
> Unless you have some balancing capability at the client with added
> intelligence of removing unavailable packet forwarders from the list of
> known servers. Though this increases the complexity of the client's
> implementation.
>
> The way we deal with a similar problem domain is as follows. Two hosts
> and two routers are selected to form a redundant cluster. Each host has
> two NICs and a serial crossover link to its mate server. Ethernet
> bonding kernel module is configured to form a bonding interface with a
> *single* MAC address assigned to both NICs in the active/standby link
> configuration. Each NIC is connected to a router (CISCO 3750, or alike)
> running HSRP protocol. The server-side connections are placed in the
> same VLAN. This gives Layer 2 redundancy and resilience to router
>
> failures or NIC failures:
> | L A N |
>
> +----+----+ HSRP +----+----+
>
> | CISCO +------+ CISCO |
> | +------+ |
>
> +----+----+ +----+----+
>
> | \ / |
> | \ / |
> | \/ |
> | VIP1 /\ VIP2 |
> | / \ |
>
> +-+-----+ +-----+-+
>
> |Server1| |Server2|
>
> +----+--+ +---+---+
>
> +-----------+
> Serial Hartbeat Link
>
> Secondly, we use http://linux-ha.org project for virtual IP management.
> Two VIPs are configurd that are owned one per active server. Clients
> talk to servers through these VIPs. Additionally a serial hartbeat link
> is used as a separate hardware path between VIP management software for
> heath checks. In the event that a server goes down or a service goes
> down for maintenance, the VIP owned by the server gets migrated to the
> other server until the former owner becomes available. This gives us
> Layer 3 redundancy.
>
> As far as the server application is concerned, do you need the servers
> running in the active-standby mode or load sharing? If the servers need
> to share some state, you could store that state in mnesia, and have it
> replicated between both nodes, while both nodes would be available
> sharing the workload.
>
> In this configuration there may not even be a need for a separate packet
> forwarder, as each TCP server would simply listen for incoming packets
> on the "0.0.0.0" address (which covers all VIPs currently managed by the
> server), and do its job, or be a protocol converter between some TCP
> protocol and Erlang terms forwarded to another Erlang gen_server process
> running in the cluster using some balancing method such as pg2 application.
>
> This approach works well for us for making highly available server
> processes.
>
> Regards,
>
> Serge
>
> Chaitanya Chalasani wrote:
> > Hi,
> >
> > We currently have a non-realtime standby server for our mission critical
> > application. In our struggle to make a realtime standby system my job is
> > to develop an application that does TCP/IP packet forwarding to the
> > active server and in an event of active server unavailability it would
> > send the packet to any of the configured standby server. The application
> > is not written in erlang, but I am planning to write the soft handover
> > application in erlang. I am attaching a test module for the same which
> > serves the purpose but I wanted to know a better design for the same or
> > any feature in erlang/OTP that can help me build more robust application.
> >
> >
> >
> > ------------------------------------------------------------------------
> >
> > -module(routerApp).
> > -compile(export_all).
> >
> >
> > listener(PortOwn,ClusterList) ->
> > case
> > gen_tcp:listen(PortOwn,[binary,{packet,0},{keepalive,true},{reuseaddr,tru
> >e}]) of {ok,LSock} ->
> > acceptConnections(LSock,ClusterList),
> > gen_tcp:close(LSock),
> > listener(PortOwn,ClusterList);
> > Other ->
> > io:format("Received ~p~n",[Other])
> > end.
> >
> > acceptConnections(LSock,ClusterList) ->
> > case gen_tcp:accept(LSock) of
> > {ok,Sock} ->
> > Pid =
> > spawn(routerApp,clientConnectionThread,[Sock,ClusterList]),
> > gen_tcp:controlling_process(Sock,Pid ),
> > acceptConnections(LSock,ClusterList);
> > {error,Reason} ->
> > io:format("Unknown error ~p~n",[Reason]);
> > Other ->
> > io:format("Unknown responce ~p~n",[Other])
> > end.
> >
> > clientConnectionThread(Sock,[{Ipaddress,Port}|ClusterList]) ->
> > case gen_tcp:connect(Ipaddress,Port ,[binary,{active,true}] ) of
> > {ok,ClustSock} ->
> > case listenForMessages(Sock,ClustSock) of
> > {error,clusterNodeClosed} ->
> >
> > clientConnectionThread(Sock,ClusterList++[{Ipaddress,Port}]);
> > {error,clientClosed} ->
> > io:format("Client Closed and so parallel thread
> > dieing~n"); Other ->
> > io:format("Unknown error ~p and so parallel thread
> > dieing~n",[Other]) end;
> > Other1 ->
> > io:format("Received ~p while connecting to ~p
> > ~n",[Other1,{Ipaddress,Port}] ),
> > clientConnectionThread(Sock,ClusterList++[{Ipaddress,Port}]) end.
> >
> > listenForMessages(Sock,ClustSock) ->
> > receive
> > {tcp_closed,ClustSock} ->
> > gen_tcp:close(ClustSock),
> > gen_tcp:close(Sock),
> > {error,clientCloses};
> > %{error,clusterNodeClosed};
> > {tcp_closed,Sock} ->
> > gen_tcp:close(Sock),
> > gen_tcp:close(ClustSock),
> > {error,clientClosed};
> > {tcp,ClustSock,Data} ->
> > io:format("Received ~w from server socket~n",[Data]),
> > gen_tcp:send(Sock,Data ),
> > listenForMessages(Sock,ClustSock);
> > {tcp,Sock,Data} ->
> > io:format("Received ~w from client socket~n",[Data]),
> > gen_tcp:send(ClustSock,Data ),
> > listenForMessages(Sock,ClustSock);
> > Other ->
> > io:format("Received unknown info ~p~n",[Other]),
> > {error,unknown}
> > end.
--
CHAITANYA CHALASANI
LINUX USER #410931
More information about the erlang-questions
mailing list