Uploaded image for project: 'MINA'
  1. MINA
  2. DIRMINA-68

Automatic reconnect configuration for client channels.

    Details

    • Type: New Feature
    • Status: Resolved
    • Priority: Major
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: 2.0.8
    • Component/s: Transport
    • Labels:
      None

      Description

      We need to provide:

      • automatic reconnect property for client sessions
      • reconnect delay
      • max retry count

      Current retry count and client session flag will be stored as session attributes.

      1. MinaFailoverSession.java
        4 kB
        Barry Kaplan
      2. ReconnectionFilter.java
        2 kB
        Julien Vermillard
      3. ReconnectionFilter.java
        3 kB
        Julien Vermillard
      4. ReconnectionFilter.java
        3 kB
        Julien Vermillard

        Activity

        Hide
        memelet Barry Kaplan added a comment -

        I attached a class that we are using for reconnection (MinaFailoverSession). It attempts to reconnect at periodic intervals (no backoff) against a set of addresses. Just idea fodder when this issue is implemented.

        Show
        memelet Barry Kaplan added a comment - I attached a class that we are using for reconnection (MinaFailoverSession). It attempts to reconnect at periodic intervals (no backoff) against a set of addresses. Just idea fodder when this issue is implemented.
        Hide
        trustin Trustin Lee added a comment -

        Thank you for your contribution, Barry. I'll take a look at it when I fix this issue.

        Show
        trustin Trustin Lee added a comment - Thank you for your contribution, Barry. I'll take a look at it when I fix this issue.
        Hide
        vrm Julien Vermillard added a comment -

        a cleaner way of implementation would be to do it as a Filter

        Show
        vrm Julien Vermillard added a comment - a cleaner way of implementation would be to do it as a Filter
        Hide
        vrm Julien Vermillard added a comment -

        a idea of implementation

        Show
        vrm Julien Vermillard added a comment - a idea of implementation
        Hide
        vrm Julien Vermillard added a comment -

        working 0.8 reconnection filter, automaticly reconnect is the session is closed

        Show
        vrm Julien Vermillard added a comment - working 0.8 reconnection filter, automaticly reconnect is the session is closed
        Hide
        vrm Julien Vermillard added a comment -

        0.9 ReconnectionFilter

        Show
        vrm Julien Vermillard added a comment - 0.9 ReconnectionFilter
        Hide
        trustin Trustin Lee added a comment -

        Thank you for your high-quality contribution. It looks good! But I want to point out some issues with this filter:

        • Some people wants to use dynamic reconnect delay. For example, the delay could be increased if connection attempt fails multiple times in a row.
        • This filter won't work if the first connection attempt fails as you noticed. I think we need a cleaner way to provide reconnection.

        For example we could provide IoConnector.setReconnectPolicy( ReconnectPolicy ) method. ReconnectPolicy will look like this:

        public abstract class ReconnectPolicy {
        public static ReconnectPolicy NEVER = ..;

        public static ReconnectPolicy getInstance(int maxAttempts, int reconnectDelay);

        public abstract long nextReconnectTime( int nAttempts, Throwable reconnectCause );
        }

        WDYT?

        Show
        trustin Trustin Lee added a comment - Thank you for your high-quality contribution. It looks good! But I want to point out some issues with this filter: Some people wants to use dynamic reconnect delay. For example, the delay could be increased if connection attempt fails multiple times in a row. This filter won't work if the first connection attempt fails as you noticed. I think we need a cleaner way to provide reconnection. For example we could provide IoConnector.setReconnectPolicy( ReconnectPolicy ) method. ReconnectPolicy will look like this: public abstract class ReconnectPolicy { public static ReconnectPolicy NEVER = ..; public static ReconnectPolicy getInstance(int maxAttempts, int reconnectDelay); public abstract long nextReconnectTime( int nAttempts, Throwable reconnectCause ); } WDYT?
        Hide
        vrm Julien Vermillard added a comment -

        so it would be a feature of IoConnector and not a filter ?

        Show
        vrm Julien Vermillard added a comment - so it would be a feature of IoConnector and not a filter ?
        Hide
        trustin Trustin Lee added a comment -

        This integration makes our life easier.

        Show
        trustin Trustin Lee added a comment - This integration makes our life easier.
        Hide
        vrm Julien Vermillard added a comment -

        we need a smart way to specify the reconnection policy. For example my needs are : try 3 times (every 2 seconds) then retry endless every minute or simply retry every second. I'm sure other MINA users got very differents needs.

        Show
        vrm Julien Vermillard added a comment - we need a smart way to specify the reconnection policy. For example my needs are : try 3 times (every 2 seconds) then retry endless every minute or simply retry every second. I'm sure other MINA users got very differents needs.
        Hide
        vrm Julien Vermillard added a comment -

        [...] So I think Trustin's idea is great.

        Show
        vrm Julien Vermillard added a comment - [...] So I think Trustin's idea is great.
        Hide
        vrm Julien Vermillard added a comment -

        putting that as a function for IoConnector will make no sense for stateless transport like DatagramConnector. It can be only for VMPipe and Socket ?

        We can perhaps implements that in socketConnector, pushing to a reconnection queue closed sessions or session with connection problems ?

        Show
        vrm Julien Vermillard added a comment - putting that as a function for IoConnector will make no sense for stateless transport like DatagramConnector. It can be only for VMPipe and Socket ? We can perhaps implements that in socketConnector, pushing to a reconnection queue closed sessions or session with connection problems ?
        Hide
        vrm Julien Vermillard added a comment -

        We could add a reconnect methond in SocketConnector :
        "public ConnectFuture reconnect(IoSession session)"

        Wich try to recycle the session by connecting it to a new channel socket and keep the filterchain and the attachements.

        Around that we can implement reconnection policies using a SessionDisconnectionHandler placed in the SocketConnector, handling connection close or failures and reconnect them.

        There is some impact on API : BaseIoSession (for reiniting closefuture), SocketConnector for adding session reconnection method, SocketSessionImpl for adding the possibility to change the SocketChannel after a reconnection.

        WDYT ?

        Show
        vrm Julien Vermillard added a comment - We could add a reconnect methond in SocketConnector : "public ConnectFuture reconnect(IoSession session)" Wich try to recycle the session by connecting it to a new channel socket and keep the filterchain and the attachements. Around that we can implement reconnection policies using a SessionDisconnectionHandler placed in the SocketConnector, handling connection close or failures and reconnect them. There is some impact on API : BaseIoSession (for reiniting closefuture), SocketConnector for adding session reconnection method, SocketSessionImpl for adding the possibility to change the SocketChannel after a reconnection. WDYT ?
        Hide
        trustin Trustin Lee added a comment -

        We can apply the same mechanism to connectionless transport types like datagram once DIRMINA-162 is resolved. Then reconnect(...) method could reside in IoConnector rather than SocketConnector.

        But would this be convenient for users? For now, IoSession.getService() returns IoService rather than IoConnector, so you need to downcast the returned value. There are also other possible options that might be more convenient and therefore we should review:

        • IoSession.reconnect() might be a viable option though it should throw a UnsupportedOperation or IllegalStateException when it is called inadequately.
        • IoSession.get/setReconnectPolicy() - we can cover most reconnection scenarios using pre-defined policy classes. These getter and setter shouldn't do anything when they are called for the sessions managed by an IoAcceptor.

        I think each approach has both its strength and weakness. What would you choose?

        Show
        trustin Trustin Lee added a comment - We can apply the same mechanism to connectionless transport types like datagram once DIRMINA-162 is resolved. Then reconnect(...) method could reside in IoConnector rather than SocketConnector. But would this be convenient for users? For now, IoSession.getService() returns IoService rather than IoConnector, so you need to downcast the returned value. There are also other possible options that might be more convenient and therefore we should review: IoSession.reconnect() might be a viable option though it should throw a UnsupportedOperation or IllegalStateException when it is called inadequately. IoSession.get/setReconnectPolicy() - we can cover most reconnection scenarios using pre-defined policy classes. These getter and setter shouldn't do anything when they are called for the sessions managed by an IoAcceptor. I think each approach has both its strength and weakness. What would you choose?
        Hide
        vrm Julien Vermillard added a comment -

        even if it's a bit confusing from the IoAcceptor point of view I agree with you and think reco policy need to go to the IoSession. We can add the reconnect to SocketConnector and wait for Datagram support for push it to IoConnector ?

        Show
        vrm Julien Vermillard added a comment - even if it's a bit confusing from the IoAcceptor point of view I agree with you and think reco policy need to go to the IoSession. We can add the reconnect to SocketConnector and wait for Datagram support for push it to IoConnector ?
        Hide
        proyal peter royal added a comment -

        After some pondering and coming back with a fresh view, IoSession.reconnect() sounds good. My only change would be to put the ReconnectionPolicy in the IoServiceConfig.

        Show
        proyal peter royal added a comment - After some pondering and coming back with a fresh view, IoSession.reconnect() sounds good. My only change would be to put the ReconnectionPolicy in the IoServiceConfig.
        Hide
        vrm Julien Vermillard added a comment -

        http://svn.apache.org/viewvc?view=rev&revision=427087

        here on my sandbox changes on SocketConnector for reconnect a IoSession

        Show
        vrm Julien Vermillard added a comment - http://svn.apache.org/viewvc?view=rev&revision=427087 here on my sandbox changes on SocketConnector for reconnect a IoSession
        Hide
        trustin Trustin Lee added a comment -

        Now, prepareToClose() (formerly unclose()) is exposed to BaseIoSession. It is used to reset the internal 'closed' status to 'not closed'. We exposed this method because we want to reuse the existing session object. As we discussed before, reusing the session instance can reduce the overhead of reconstructing the filter chain. (Do I remember correctly?) But all other attributes and properties should be cleared so they could be set by IoHandler implementation. We don't have any control over the attributes that might contain critical state information that might affect the behavior of an application. Actually we also don't have any control over the insertion and removal of filters in the middle of a connection, so it makes us very hard to reuse a session instance.

        So, here's my idea:

        1. Create IoConnectorSession interface which extends IoSession and provides 'ConnectFuture reconnect()'
        2. Create an implementation of IoConnectorSession which wraps existing IoSession implementations and takes care of all reconnection process (i.e. calling IoConnector.connect() again and switching the wrapped session)
        3. IoConnector.connect() wraps the original IoSession implementation (e.g. SocketSession) with the IoConnectorSession implementation.

        I think this will minimize changes in our code and enables us to provide reconnection feature more easily for future transport implementations.

        There's one problem though; how can we get the original session instance from IoConnectorSession instance if IoConnector.connect() returns a wrapped session? We need to find out a trick.

        Show
        trustin Trustin Lee added a comment - Now, prepareToClose() (formerly unclose()) is exposed to BaseIoSession. It is used to reset the internal 'closed' status to 'not closed'. We exposed this method because we want to reuse the existing session object. As we discussed before, reusing the session instance can reduce the overhead of reconstructing the filter chain. (Do I remember correctly?) But all other attributes and properties should be cleared so they could be set by IoHandler implementation. We don't have any control over the attributes that might contain critical state information that might affect the behavior of an application. Actually we also don't have any control over the insertion and removal of filters in the middle of a connection, so it makes us very hard to reuse a session instance. So, here's my idea: 1. Create IoConnectorSession interface which extends IoSession and provides 'ConnectFuture reconnect()' 2. Create an implementation of IoConnectorSession which wraps existing IoSession implementations and takes care of all reconnection process (i.e. calling IoConnector.connect() again and switching the wrapped session) 3. IoConnector.connect() wraps the original IoSession implementation (e.g. SocketSession) with the IoConnectorSession implementation. I think this will minimize changes in our code and enables us to provide reconnection feature more easily for future transport implementations. There's one problem though; how can we get the original session instance from IoConnectorSession instance if IoConnector.connect() returns a wrapped session? We need to find out a trick.
        Hide
        trustin Trustin Lee added a comment -

        Another use case from Joao:
        ===========================

        Sorry for this new buy question...
        I have a server(kinda proxy) that connects to two connection upstream .
        In fact, it will connect to the second socket only if the first
        socket goes down.
        The second connection/socket is more of a failover option.

        Is a future like this already implemented in mina?

        Is there an easy way to implement it using the present connector
        infrastructure?

        Show
        trustin Trustin Lee added a comment - Another use case from Joao: =========================== Sorry for this new buy question... I have a server(kinda proxy) that connects to two connection upstream . In fact, it will connect to the second socket only if the first socket goes down. The second connection/socket is more of a failover option. Is a future like this already implemented in mina? Is there an easy way to implement it using the present connector infrastructure?
        Hide
        vinod.p Vinod Panicker added a comment -

        What we are working on exactly fits Joao's use case.

        In effect, its a mina submodule that would be designed to establish communication channels with a peer/peers. It would be specifically designed to carry huge volumes of data, with support for failover as well. Basically a twin connection will be held in reserve and will be used if the first fails.

        To start with, it will support a p2p connection and will be enhanced later(if needed) for one-to-many connections/multicasting.

        Will this be of use as a sub-module? I'm willing to donate the source once its done.

        Show
        vinod.p Vinod Panicker added a comment - What we are working on exactly fits Joao's use case. In effect, its a mina submodule that would be designed to establish communication channels with a peer/peers. It would be specifically designed to carry huge volumes of data, with support for failover as well. Basically a twin connection will be held in reserve and will be used if the first fails. To start with, it will support a p2p connection and will be enhanced later(if needed) for one-to-many connections/multicasting. Will this be of use as a sub-module? I'm willing to donate the source once its done.
        Hide
        trustin Trustin Lee added a comment -

        Will fix this in 2.0.0-M1 because it might affect the overall API design on the connector side.

        Show
        trustin Trustin Lee added a comment - Will fix this in 2.0.0-M1 because it might affect the overall API design on the connector side.
        Hide
        trustin Trustin Lee added a comment -
        Show
        trustin Trustin Lee added a comment - http://tinyurl.com/2lu7z3
        Hide
        trustin Trustin Lee added a comment -

        From the recent discussion, we concluded we don't need any core API modification. Therefore, we can implement this feature later, but at least before 2.0.0-RC1.

        Show
        trustin Trustin Lee added a comment - From the recent discussion, we concluded we don't need any core API modification. Therefore, we can implement this feature later, but at least before 2.0.0-RC1.
        Hide
        elecharny Emmanuel Lecharny added a comment -

        A seven years old discussion about a feature nobody seems to require...

        Show
        elecharny Emmanuel Lecharny added a comment - A seven years old discussion about a feature nobody seems to require...

          People

          • Assignee:
            Unassigned
            Reporter:
            trustin Trustin Lee
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development