Проблема параллелизма OpenLDAP 2.3/2.4

Проблемы с параллелизмом при аутентификации и других запросах на чтение с помощью Open LDAP (проверенная версия 2.3.43 и 2.4.39)

При выполнении 100 одновременных запросов на привязку тестовый код занимает около 150 миллисекунд. При увеличении этого числа до 1000 одновременных запросов время увеличивается до 9303 миллисекунд. Таким образом, из 10 одновременных запросов мы наблюдаем 62-кратное увеличение времени выполнения.

Это ожидаемое поведение? Или чего-то не хватает в нашей конфигурации сервера OpenLDAP/конфигурации хоста Linux?

ПРИМЕЧАНИЕ. Мы запустили этот тестовый код на сервере Apache DS 2.0.0 на базе Windows (такая же древовидная структура и т. д.) для сравнения, а на этом сервере результаты производительности оказались такими, как мы обычно ожидаем (т.е. 100x занимает ~80 мс, 1000x занимает ~ 400 мс, 10 000x занимает ~ 2700 мс)

Настройки в slapd.conf:

cachesize       100000
idlcachesize    300000
database        bdb
suffix          "dc=company,dc=com"
rootdn          "uid=admin,ou=system"
rootpw          secret
directory       /var/lib/ldap
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub
sizelimit       100000
loglevel        256

Тестовый код:

import java.util.ArrayList;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
public class DirectoryServiceMain {
    public static void main(String[] args) {
        int concurrentThreadCount = 100;

        LdapContextSource ctx = new LdapContextSource();

        ctx.setUrls(new String [] { "ldap://ldap1.dev.company.com:389/", "ldap://ldap1.dev.company.com:389/" });
        ctx.setBase("dc=company,dc=com");
        ctx.setUserDn("uid=admin,ou=system");
        ctx.setPassword("secret");

        ctx.setPooled(true);
        ctx.setCacheEnvironmentProperties(false);
        LdapTemplate template = new LdapTemplate();
        template.setContextSource(ctx);

        long startTime = System.currentTimeMillis();
        ArrayList<Thread> threads = new ArrayList<>();
        for(int i = 0; i < concurrentThreadCount; i++) {
            Thread t = new Thread(
                () ->  {                   
                    DirContext context = template.getContextSource().getContext("uid=username,dc=users,uid=office,dc=suborganisations,uid=ABC,dc=organisations,dc=company,dc=com",
                                                                           "password");
                    try {
                        context.close();
                    } catch(NamingException e) {}

                });

            t.start();
            threads.add(t);
        }

        boolean alive = true;
        while(alive) {
            alive = false;
            for(Thread t : threads) {
                if(t.isAlive()) {
                    alive = true;
                    try {Thread.sleep(10);} catch(InterruptedException e) {}
                } 
            }
        }

        long endTime = System.currentTimeMillis();

        System.out.println("Total time: " + (endTime - startTime));
    }
}

улимит -n 131072

* ОБНОВЛЕНИЕ * Если небольшая задержка (например, Thread.sleep(1)) добавляется после каждого t.start(), то время обработки n параллельных потоков значительно сокращается.


person Going Bananas    schedule 11.12.2014    source источник
comment
Краткий ответ - да'. Время отклика в зависимости от нагрузки не является линейным.   -  person user207421    schedule 12.12.2014


Ответы (1)


Более длинный ответ: если вы используете BDB в качестве базы данных, вы, вероятно, увидите проблемы с линейным масштабированием выше определенного количества одновременных запросов. BDB имеет собственный файл db_config, который можно настроить для обеспечения лучших характеристик производительности. Вы также можете подумать о переходе на MDB, который был специально написан для открытого ldap и имеет лучшее линейное масштабирование с минимальной конфигурацией.

Вам также следует рассмотреть возможность ограничения количества одновременных подключений, установив размеры пула соединений jndi ldap в соответствии с LDAPContextSource:

Map<String, Object> map = new HashMap<>();
map.put("com.sun.jndi.ldap.connect.pool.initsize", 2);
map.put("com.sun.jndi.ldap.connect.pool.maxsize", 2);
map.put("com.sun.jndi.ldap.connect.pool.prefsize", 2);
ctx.setBaseEnvironmentProperties(map);
person Aestel    schedule 12.12.2014