【问题标题】:Threaded ldap modify on a web applicationWeb 应用程序上的线程化 ldap 修改
【发布时间】:2013-07-19 15:07:58
【问题描述】:

我有一个 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 进行批量修改?

【问题讨论】:

    标签: java spring web-applications ldap spring-batch


    【解决方案1】:

    您可以查看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 了解更多信息

    【讨论】:

    • 非常感谢!我要试试这个。我不知道 spring 批处理库.. 目前我正在使用 java executor 管理它。这看起来好多了,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多