0

我有一个 Web 应用程序,它每天对 ldap 数据库进行搜索。这是通过调度任务的 spring ldap 库完成的。此搜索将返回大约 20000 个结果。然后我希望修改所有这些用户的属性,这是问题开始的地方。我真的希望有一个像在关系数据库中那样的组修改功能,你会做类似的事情(set a=x where b

所以我尝试了两种方法:

遍历每个用户,并执行如下所示的操作:

DistinguishedName userDn = buildDn(user);
  DirContextOperations dtCtx = ldapTemplate.lookupContext(userDn);

  for(int i = 0; i < attributes.length; i++){
      dtCtx.setAttributeValue(attributes[i], values[i]);
  }
  ldapTemplate.modifyAttributes(dtCtx);

哪个有效,但非常耗时。

第二种方法与第一种方法相同,但切分用户列表并多线程修改。哪个工作得更快,但仍然不能很好地扩展。ldap 是一个 opends 数据存储。

有没有更好的方法可以从 Web 应用程序对 ldap 进行批量修改?

4

1 回答 1

2

您可以查看一种Spring Batch模式,其中建立了所有用户的单个列表,然后使用线程池将每个用户传递、修改并提交给 ldap 服务器。

配置可能如下所示;

<batch:job id="ldapJob">
    <batch:step id="ldapJob.step1">
        <batch:tasklet task-executor="taskExecutor">
            <batch:chunk reader="ldapReader" processor="ldapModifier" writer="ldapWriter" commit-interval="1"/>
        </batch:tasklet>
    </batch:step>
</batch:job>

<task:executor id="taskExecutor"/>

和这样的读者在一起

package de.incompleteco.spring.batch.item.reader;

import java.util.Queue;

import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.ldap.core.DirContextOperations;

public class LdapItemReader implements ItemReader<DirContextOperations> {

    private Queue<DirContextOperations> dirContextOperations;

    public DirContextOperations read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if (dirContextOperations == null) {
            synchronized (this) {
                //load up the dirContextOperations into the queue
            }//end synch
        }//end if
        //retrieve
        return dirContextOperations.poll();
    }

}

处理器;

package de.incompleteco.spring.batch.item.processor;

import org.springframework.batch.item.ItemProcessor;
import org.springframework.ldap.core.DirContextOperations;

public class LdapItemProcessor implements ItemProcessor<DirContextOperations, DirContextOperations> {

    public DirContextOperations process(DirContextOperations item) throws Exception {
        //do some update
        item.setAttributeValue(null, null);
        //return
        return item;
    }

}

最后是 ldap 服务器的作者

package de.incompleteco.spring.batch.item.writer;

import java.util.List;

import org.springframework.batch.item.ItemWriter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;

public class LdapItemWriter implements ItemWriter<DirContextOperations> {

    private LdapTemplate ldapTemplate;

    public void write(List<? extends DirContextOperations> items) throws Exception {
        for (DirContextOperations operation : items) {
            ldapTemplate.modifyAttributes(operation);
        }
    }

    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }

}

这种模式的关键是使用任务执行器来允许您对进程进行多线程处理,读者首先负责构建队列/列表(20k 条记录),然后每个线程将轮询用户,使改变,把它放回去。

此模式不允许重试,因此您可能需要查看加载策略,但它会为您提供可以在 WAR 中运行的体面的线程池可扩展更新解决方案。

查看spring-batch以获取更多信息

于 2013-07-19T15:38:13.357 回答