You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2021/01/29 13:29:15 UTC

[ignite] branch master updated: IGNITE-13763: Add connection limit

This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 165d5cc  IGNITE-13763: Add connection limit
165d5cc is described below

commit 165d5ccad1a780b008dfe8cb953bc6a0f6347067
Author: Igor Sapego <is...@apache.org>
AuthorDate: Fri Jan 29 16:28:07 2021 +0300

    IGNITE-13763: Add connection limit
    
    This closes #8726
---
 .../cpp/thin-client-test/config/log/log4j-0.xml    | 42 +++++++++++++
 .../cpp/thin-client-test/config/with-logging-0.xml | 36 +++++++++++
 .../thin-client-test/config/with-logging-base.xml  | 70 ++++++++++++++++++++++
 .../cpp/thin-client-test/include/test_utils.h      |  8 +++
 .../thin-client-test/src/ignite_client_test.cpp    | 68 +++++++++++++++++++--
 .../cpp/thin-client-test/src/test_utils.cpp        | 17 ++++++
 .../ignite/thin/ignite_client_configuration.h      | 37 +++++++++++-
 .../cpp/thin-client/src/impl/data_router.cpp       | 10 ++++
 8 files changed, 283 insertions(+), 5 deletions(-)

diff --git a/modules/platforms/cpp/thin-client-test/config/log/log4j-0.xml b/modules/platforms/cpp/thin-client-test/config/log/log4j-0.xml
new file mode 100644
index 0000000..90a1cb8
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/config/log/log4j-0.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<Configuration>
+    <Appenders>
+        <Console name="CONSOLE" target="SYSTEM_OUT">
+            <PatternLayout pattern="[%d{ISO8601}][%-5p][%t][%c{1}] %m%n"/>
+        </Console>
+        <RollingFile name="FILE" append="true"
+                     filePattern="logs/ignite-log-0-%i.log.gz"
+                     fileName="logs/ignite-log-0.txt">
+            <PatternLayout pattern="%m%n"/>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="10MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+        </RollingFile>
+    </Appenders>
+    <Loggers>
+        <Logger name="org.apache.ignite.internal.processors.odbc.ClientListenerNioListener" level="debug"/>
+        <Root level="info">
+            <AppenderRef ref="CONSOLE"/>
+            <AppenderRef ref="FILE"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/modules/platforms/cpp/thin-client-test/config/with-logging-0.xml b/modules/platforms/cpp/thin-client-test/config/with-logging-0.xml
new file mode 100644
index 0000000..3a52964
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/config/with-logging-0.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+    <import resource="with-logging-base.xml"/>
+
+    <bean parent="test.cfg">
+        <property name="gridLogger">
+            <bean class="org.apache.ignite.logger.log4j2.Log4J2Logger">
+                <constructor-arg type="java.lang.String" value="${IGNITE_NATIVE_TEST_CPP_THIN_CONFIG_PATH}/log/log4j-0.xml"/>
+            </bean>
+        </property>
+    </bean>
+</beans>
diff --git a/modules/platforms/cpp/thin-client-test/config/with-logging-base.xml b/modules/platforms/cpp/thin-client-test/config/with-logging-base.xml
new file mode 100644
index 0000000..cba28da
--- /dev/null
+++ b/modules/platforms/cpp/thin-client-test/config/with-logging-base.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+
+    <!--
+        Initialize property configurer so we can reference environment variables.
+    -->
+    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_FALLBACK"/>
+        <property name="searchSystemEnvironment" value="true"/>
+    </bean>
+  
+    <bean abstract="true" id="test.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration"><null/></property>
+
+        <property name="clientConnectorConfiguration">
+            <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
+                <property name="host" value="127.0.0.1"/>
+                <property name="port" value="11110"/>
+            </bean>
+        </property>
+
+        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <!--
+                        Ignite provides several options for automatic discovery that can be used
+                        instead os static IP based discovery.
+                    -->
+                    <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. -->
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <!-- In distributed environment, replace with actual host IP address. -->
+                                <value>127.0.0.1:47500</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+                <property name="socketTimeout" value="300" />
+            </bean>
+        </property>
+    </bean>
+</beans>
diff --git a/modules/platforms/cpp/thin-client-test/include/test_utils.h b/modules/platforms/cpp/thin-client-test/include/test_utils.h
index 0d8e2b6..e0f0ff5 100644
--- a/modules/platforms/cpp/thin-client-test/include/test_utils.h
+++ b/modules/platforms/cpp/thin-client-test/include/test_utils.h
@@ -75,6 +75,14 @@ namespace ignite_test
      * Remove all the LFS artifacts.
      */
     void ClearLfs();
+
+    /**
+     * Get a number of occurrences of a given string in the specified file.
+     * @param filePath File path.
+     * @param line Line to find.
+     * @return Number of occurrences.
+     */
+    size_t GetLineOccurrencesInFile(const std::string& filePath, const std::string& line);
 }
 
 #endif // _IGNITE_THIN_CLIENT_TEST_TEST_UTILS
\ No newline at end of file
diff --git a/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp b/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp
index 0010d4f..bb50b16 100644
--- a/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp
+++ b/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp
@@ -32,7 +32,7 @@ class IgniteClientTestSuiteFixture
 public:
     IgniteClientTestSuiteFixture()
     {
-        serverNode = ignite_test::StartCrossPlatformServerNode("cache.xml", "ServerNode");
+        // No-op.
     }
 
     ~IgniteClientTestSuiteFixture()
@@ -40,15 +40,53 @@ public:
         ignite::Ignition::StopAll(false);
     }
 
-private:
-    /** Server node. */
-    ignite::Ignite serverNode;
+    /**
+     * Check that if client started with given configuration and connection limit then the actual number of active
+     * connections is equal to the expected value.
+     *
+     * @param cfg Client configuration.
+     * @param limit Limit to set
+     * @param expect Expected connections number.
+     */
+    void CheckConnectionsNum(IgniteClientConfiguration &cfg, uint32_t limit, size_t expect)
+    {
+        cfg.SetConnectionsLimit(limit);
+        IgniteClient client = IgniteClient::Start(cfg);
+
+        BOOST_CHECK_EQUAL(GetActiveConnections(), expect);
+    }
+
+    /**
+     * Get Number of active connections.
+     *
+     * @return Number of active connections.
+     */
+    static size_t GetActiveConnections()
+    {
+        size_t connected = ignite_test::GetLineOccurrencesInFile("logs/ignite-log-0.txt", "Client connected");
+        size_t disconnected = ignite_test::GetLineOccurrencesInFile("logs/ignite-log-0.txt", "Client disconnected");
+
+        return connected - disconnected;
+    }
+
+    /**
+     * Start node with logging.
+     *
+     * @param id Node id. Used to identify node and log.
+     */
+    ignite::Ignite StartNodeWithLog(const std::string& id)
+    {
+        std::string nodeName = "ServerNode" + id;
+        return ignite_test::StartCrossPlatformServerNode("with-logging-0.xml", nodeName.c_str());
+    }
 };
 
 BOOST_FIXTURE_TEST_SUITE(IgniteClientTestSuite, IgniteClientTestSuiteFixture)
 
 BOOST_AUTO_TEST_CASE(IgniteClientConnection)
 {
+    ignite::Ignite serverNode = ignite_test::StartCrossPlatformServerNode("cache.xml", "ServerNode");
+
     IgniteClientConfiguration cfg;
 
     cfg.SetEndPoints("127.0.0.1:11110");
@@ -58,6 +96,8 @@ BOOST_AUTO_TEST_CASE(IgniteClientConnection)
 
 BOOST_AUTO_TEST_CASE(IgniteClientConnectionFailover)
 {
+    ignite::Ignite serverNode = ignite_test::StartCrossPlatformServerNode("cache.xml", "ServerNode");
+
     IgniteClientConfiguration cfg;
 
     cfg.SetEndPoints("127.0.0.1:11109..11111");
@@ -65,4 +105,24 @@ BOOST_AUTO_TEST_CASE(IgniteClientConnectionFailover)
     IgniteClient::Start(cfg);
 }
 
+BOOST_AUTO_TEST_CASE(IgniteClientConnectionLimit)
+{
+    ignite::common::DeletePath("logs");
+
+    ignite::Ignite serverNode0 = StartNodeWithLog("0");
+    ignite::Ignite serverNode1 = StartNodeWithLog("1");
+    ignite::Ignite serverNode2 = StartNodeWithLog("2");
+
+    IgniteClientConfiguration cfg;
+
+    cfg.SetEndPoints("127.0.0.1:11110,127.0.0.1:11111,127.0.0.1:11112");
+
+    CheckConnectionsNum(cfg, 0, 3);
+    CheckConnectionsNum(cfg, 1, 1);
+    CheckConnectionsNum(cfg, 2, 2);
+    CheckConnectionsNum(cfg, 3, 3);
+    CheckConnectionsNum(cfg, 4, 3);
+    CheckConnectionsNum(cfg, 100500, 3);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/platforms/cpp/thin-client-test/src/test_utils.cpp b/modules/platforms/cpp/thin-client-test/src/test_utils.cpp
index 427490b..fd179d2 100644
--- a/modules/platforms/cpp/thin-client-test/src/test_utils.cpp
+++ b/modules/platforms/cpp/thin-client-test/src/test_utils.cpp
@@ -19,6 +19,8 @@
 
 #include <cassert>
 
+#include <fstream>
+
 #include <ignite/common/platform_utils.h>
 
 #include "test_utils.h"
@@ -136,4 +138,19 @@ namespace ignite_test
 
         ignite::common::DeletePath(workDir);
     }
+
+    size_t GetLineOccurrencesInFile(const std::string& filePath, const std::string& line)
+    {
+        std::ifstream file(filePath.c_str());
+
+        size_t cnt = 0;
+        std::string current;
+        while (std::getline(file, current))
+        {
+            if (current.find(line) != std::string::npos)
+                ++cnt;
+        }
+
+        return cnt;
+    }
 }
diff --git a/modules/platforms/cpp/thin-client/include/ignite/thin/ignite_client_configuration.h b/modules/platforms/cpp/thin-client/include/ignite/thin/ignite_client_configuration.h
index d14f830..617009f 100644
--- a/modules/platforms/cpp/thin-client/include/ignite/thin/ignite_client_configuration.h
+++ b/modules/platforms/cpp/thin-client/include/ignite/thin/ignite_client_configuration.h
@@ -46,7 +46,8 @@ namespace ignite
              */
             IgniteClientConfiguration() :
                 sslMode(SslMode::DISABLE),
-                partitionAwareness(false)
+                partitionAwareness(false),
+                connectionsLimit(0)
             {
                 // No-op.
             }
@@ -230,6 +231,37 @@ namespace ignite
                 return partitionAwareness;
             }
 
+            /**
+             * Get connection limit.
+             *
+             * By default, C++ thin client establishes a connection to every server node listed in @c endPoints. Use
+             * this setting to limit the number of active connections. This reduces initial connection time and the
+             * resource usage, but can have a negative effect on cache operation performance, especially if partition
+             * awareness is used.
+             *
+             * Zero value means that number of active connections is not limited.
+             *
+             * The default value is zero.
+             *
+             * @return Active connection limit.
+             */
+            uint32_t GetConnectionsLimit() const
+            {
+                return connectionsLimit;
+            }
+
+            /**
+             * Set connection limit.
+             *
+             * @see GetConnectionsLimit for details.
+             *
+             * @param connectionsLimit Connections limit to set.
+             */
+            void SetConnectionsLimit(uint32_t limit)
+            {
+                connectionsLimit = limit;
+            }
+
         private:
             /** Connection end points */
             std::string endPoints;
@@ -254,6 +286,9 @@ namespace ignite
 
             /** Partition awareness. */
             bool partitionAwareness;
+
+            /** Active connections limit. */
+            uint32_t connectionsLimit;
         };
     }
 }
diff --git a/modules/platforms/cpp/thin-client/src/impl/data_router.cpp b/modules/platforms/cpp/thin-client/src/impl/data_router.cpp
index ea672ad..0943afa 100644
--- a/modules/platforms/cpp/thin-client/src/impl/data_router.cpp
+++ b/modules/platforms/cpp/thin-client/src/impl/data_router.cpp
@@ -111,6 +111,16 @@ namespace ignite
                             break;
                         }
                     }
+
+                    if (config.GetConnectionsLimit())
+                    {
+                        common::concurrent::CsLockGuard lock(channelsMutex);
+
+                        size_t connectionsNum = newLegacyChannels.size() + channels.size();
+
+                        if (connectionsNum >= config.GetConnectionsLimit())
+                            break;
+                    }
                 }
 
                 common::concurrent::CsLockGuard lock(channelsMutex);