You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Aleksandr Polovtcev (Jira)" <ji...@apache.org> on 2021/11/24 18:15:00 UTC

[jira] [Assigned] (IGNITE-15988) ConnectionManager can violate the message ordering contract

     [ https://issues.apache.org/jira/browse/IGNITE-15988?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Aleksandr Polovtcev reassigned IGNITE-15988:
--------------------------------------------

    Assignee: Aleksandr Polovtcev

> ConnectionManager can violate the message ordering contract
> -----------------------------------------------------------
>
>                 Key: IGNITE-15988
>                 URL: https://issues.apache.org/jira/browse/IGNITE-15988
>             Project: Ignite
>          Issue Type: Bug
>          Components: networking
>            Reporter: Aleksandr Polovtcev
>            Assignee: Aleksandr Polovtcev
>            Priority: Major
>              Labels: ignite-3
>
> {{MessagingService#send}} method defines the following contract:
> # Messages will be delivered in the same order as they were sent
> # If a message N has been successfully delivered to a member implies that all messages preceding N have also been successfully delivered.
> However, the current underlying implementation can violate this contract in a specific case. This can happen due to the following code in the {{ConnectionManager#channel}} method:
> {code:java}
> if (consistentId != null) {
>     // If consistent id is known, try looking up a channel by consistent id. There can be an outbound connection
>     // or an inbound connection associated with that consistent id.
>     NettySender channel = channels.compute(
>             consistentId,
>             (addr, sender) -> (sender == null || !sender.isOpen()) ? null : sender
>     );
>     ...
> }
> // Get an existing client or create a new one. NettyClient provides a CompletableFuture that resolves
> // when the client is ready for write operations, so previously started client, that didn't establish connection
> // or didn't perform the handhsake operaton, can be reused.
> NettyClient client = clients.compute(address, (addr, existingClient) ->
>         existingClient != null && !existingClient.failedToConnect() && !existingClient.isDisconnected()
>                 ? existingClient : connect(addr)
> );
> {code}
> Imaging the following situation, given two nodes, called node 1 and node 2:
> # Node 1 and node 2 start, nothing happens on the membership level yet.
> # Node 1 sends a message to node 2 using the {{MessagingService#send(NetworkAddress ...)}} method.
> # In the meantime node 2 discovers the node 1 and sends a message to it using the {{MessagingService#send(ClusterNode ...)}} method.
> # Node 1 sends another message to node2, this time an incoming channel, opened in step 3, will be reused. This means that the first and the second message from node 1 will be sent over two different channels, which may not obey the aforementioned contract.
> h3. Possible solution
> A possible solution might be to always check whether the {{clients}} map contains the destination address and to prefer to use its channel. 



--
This message was sent by Atlassian Jira
(v8.20.1#820001)