Проблемы с параллелизмом при аутентификации и других запросах на чтение с помощью 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 параллельных потоков значительно сокращается.