`
darkjune
  • 浏览: 308517 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

SymmetricDS 2.2.5 undeploy时symmetricScheduler job线程杀不掉分析

阅读更多

SymmetricDS的同步机制是定时周期性同步,我们项目根据业务需要,只需要客户在UI激活一次replication时候才开始同步,所以这里我们的设计是每次激活时,用symmetric自己的deploy/undeploy机制让其在启动时候自动跑replication任务。

 

最近遇到一个问题, 在使用中,发现当数据同步时间间隔设在1小时以内时,运行一天以上会发现大量的SymmetricSchedule线程积压在JVM中没有释放,怀疑是Symmetric 2.2.5中在undeploy时释放线程有问题。

为了解决这个问题,先看下SymmetricDS中其需要的定时任务都定义在哪里。

 

在Symmetric engine中,整个symmetricDS的入口类在AbstractSymmetricEngine,在这个类的启动方法如下:

 

    public synchronized boolean start() {

        setup();
        
        if (isConfigured()) {
                  ...
                    getTriggerRouterService().syncTriggers();
                    heartbeat(false);
                    jobManager.startJobs();
                   ...
                    started = true;
                } finally {
                    starting = false;
                }
                
                return true;
            } else {
                return false;
            }
        } else {
           ...
        }
    }
 

 

可以看到其内置的job是由jobManager启动的,再看其实现类JobManager代码片段:

 

  private List<IJob> jobs;  

  public synchronized void startJobs() {
        for (IJob job : jobs) {
            if (job.isAutoStartConfigured()) {
                job.start();
            } else {
                log.info("JobNoAutoStart", job.getName());
            }
        }
    }
 可以看到是直接调用集合jobs中的job实例,该实例在SymmetricDS 2 中是由spring注入的,其spring xml配置如下:

 

 

    <bean id="jobManager" class="org.jumpmind.symmetric.job.JobManager">
        <property name="jobs">
            <list>
                <ref bean="job.routing" />
                <ref bean="job.push" />
                <ref bean="job.pull" />
                <ref bean="job.purge.outgoing" />
                <ref bean="job.purge.incoming" />
                <ref bean="job.purge.datagaps" />
                <ref bean="job.stat.flush" />
                <ref bean="job.synctriggers" />
                <ref bean="job.heartbeat" />
                <ref bean="job.watchdog" />
            </list>
        </property>
        <property name="taskScheduler" ref="symmetricScheduler" />
    </bean>
    <bean id="job.routing" parent="job.abstract" class="org.jumpmind.symmetric.job.RouterJob">
        <property name="routingService" ref="routingService" />
        <property name="autoStartParameterName" value="start.route.job" />
    </bean>
 以上就是其内置的job,支持周期性运行和定时运行,以便进行数据库同步。这些job就是在undeploy时候没有杀掉的线程,由于我们关注的是undeploy时这些job的卸载情况,回到AbstractSymmetricEngine:

 

 

private ThreadPoolTaskScheduler taskScheduler;    
public synchronized void stop() {
        ...
        jobManager.stopJobs();
        getRouterService().stop();
        started = false;
        starting = false;
    }
    public synchronized void destroy () {
        stopJobs();
    }
 回到JobManager:

 

 

    public synchronized void stopJobs() {
        for (IJob job : jobs) {
            job.stop();
        }      
    }
 

 

jobManager直接遍历每个job并调用其stop方法。

所有job都有个超类AbstractJob,这个类的stop方法如下:

 

    public boolean stop() {
        boolean success = false;
        if (this.scheduledJob != null) {
            success = this.scheduledJob.cancel(true);
            this.scheduledJob = null;
            if (success) {
                log.info("JobCancelled", jobName);
                started = false;                
            } else {
                log.warn("JobFailedToCancel", jobName);
            }
        }
        return success;
    }
 这里只是调用了线程的cancel方法,在我们实际使用中,只是cancel并没有终结掉这些线程,这是我们JVM中的thread dump:

 

 

"symmetricScheduler-14" prio=6 tid=0x49d7f800 nid=0x13b4 waiting on condition [0x4e2ef000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x1d6873b8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2025)
at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:609)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:602)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:662)

 

找到这里,我们知道这是其释放线程的一个bug,所以我直接去找了一下symmetricDS的bug track里有没有解决,发现这是2.2.*中的一个bug,在2.4.0以后的版本中已经fix,其JIRA地址在:

Tomcat shutdown hangs when SymmetricDS is deployed as a war 写道
http://jira.codehaus.org/browse/SYMMETRICDS-466?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel

 

这个fix主要是在JobManager中加入了调用spring的线程池的shutdow方法:

    public synchronized void destroy () {
        stopJobs();
        if (taskScheduler != null) {
            taskScheduler.shutdown();
        }
    }

 

至此,在项目中使用symmetricDS新的代码,undeploy后线程都被杀掉,重新deploy后没有多余的job线程运行。

 

我们的启动方式:

没有在配置文件中配SymmetricDS需要的.cron项,直接让其按照线程的scheduleWithFixedDelay方式运行。该任务模式的配置在symmetric.properties文件中,在symmetric源码(AbstractJob)中可以清晰的看到如何获取该配置文件的值:

this.cronExpression = parameterService.getString(jobName + ".cron", null);

 之后在该类的启动线程方法中会有判断:

    public void start() {
        if (this.scheduledJob == null) {
            log.info("JobStarting", jobName);
            if (!StringUtils.isBlank(cronExpression)) {
                this.scheduledJob = taskScheduler.schedule(this, new CronTrigger(cronExpression));
                started = true;
            } else {

                int startDelay = randomTimeSlot.getRandomValueSeededByExternalId();
                if (this.timeBetweenRunsInMs > 0) {
                    this.scheduledJob = taskScheduler.scheduleWithFixedDelay(this,
                            new Date(System.currentTimeMillis() + startDelay),
                            this.timeBetweenRunsInMs);
                    started = true;
                } else {
                    log.error("JobFailedToSchedule", jobName);
                }
            }
        }
    }

 

 

下面是正常后的JVM 线程截图:

 

 
  • 大小: 90.8 KB
分享到:
评论
2 楼 darkjune 2014-12-19  
他整个同步机制官方网站文档都有,同步时是在临时文件夹将需要发送的数据变成了csv文件。如果同时更新同一张表,有一个filter机制来放弃重复更新,filter规则支持自定义。
1 楼 yuanfangren123 2014-12-06  
您好,我目前只是配置成功了。我想问下这个软件他在同步的时候数据是如何传输的?有没有形成文件,通过文件来传输?还有就是他如何避免两表双向同步的时候触发器之间的来回触发问题?您能说下他的源码的大体流程吗?
您还有他的一些其他的相关资料吗?

相关推荐

    AForge.dll 2.2.5版本

    对于运动检测,AForge.dll 2.2.5可能提供了基于背景减除、光流分析等方法的实现,使得开发者能够检测视频流中的动态变化,这对于安全监控、行为分析等领域至关重要。 在实际应用中,例如智能安防系统,开发者可以...

    Keras-2.2.5.tar.gz

    在本资源中,我们讨论的是 Keras 的版本 2.2.5,这是一个非常稳定且广泛使用的版本。 Keras 的主要特点包括: 1. **用户友好**:Keras 提供了一种直观且易于理解的接口,使得构建复杂的深度学习模型变得简单。它...

    vagrant_2.2.5_x86_64.rar

    这个“vagrant_2.2.5_x86_64.rar”文件是Vagrant的一个特定版本,即2.2.5,适用于64位(x86_64)的系统。Vagrant通过自动化虚拟化技术,如VirtualBox、VMware或AWS,让开发者能够快速地创建一致且可重复使用的开发...

    android_2.2.5.rar

    1. **应用程序运行速度提升**:Android 2.2.5引入了Dalvik虚拟机的Just-In-Time (JIT)编译,使得程序在运行时能被即时编译为机器代码,显著提高了应用的执行效率。 2. **内存管理优化**:系统对内存分配和回收进行...

    glibc-2.2.5.tar.gz

    5. **线程支持**:glibc提供了线程创建、同步和通信的API,如pthread_create、pthread_join、mutex、condition_variable等,使得多线程编程成为可能。 6. **动态链接**:glibc支持动态链接,使得程序可以在运行时...

    gxt-2.2.5.zip

    与2.1.1版本相比,2.2.5在性能上有所提升,减少了页面加载时间和内存占用,提高了用户界面的响应速度,尤其在处理大量数据时,表现更加出色。 4. **主题与皮肤**: GXT提供了多种预设主题,如blue、gray、classic...

    vagrant_2.2.5的64位版本

    总之,Vagrant 2.2.5 是一个强大且灵活的工具,通过它,开发者可以轻松创建和管理虚拟开发环境,提高工作效率,减少环境中出现的不一致性和问题。下载并使用这个64位版本的Vagrant,将使你的开发流程更加顺畅。

    AForge.NET Framework-2.2.5

    AForge.NET Framework-2.2.5 文档 源码 例子

    hornetq-2.2.5.Final.zip

    hornetq-2.2.5.Final.ziphornetq-2.2.5.Final.ziphornetq-2.2.5.Final.ziphornetq-2.2.5.Final.ziphornetq-2.2.5.Final.ziphornetq-2.2.5.Final.ziphornetq-2.2.5.Final.zip

    Highcharts-2.2.5源码

    标题“Highcharts-2.2.5源码”表明我们将要探讨的是Highcharts的2.2.5版本的源代码。这个版本可能包含了该版本发布时的所有功能和修复的已知问题。通过查看源码,开发者可以深入理解其工作原理,自定义图表行为,...

    Vagrant2.2.5版本64位

    Vagrant2.2.5是该软件的一个具体版本,适用于64位操作系统。这个版本提供了对不同操作系统和虚拟化技术(如VirtualBox、VMware等)的支持,使得开发人员可以方便地配置和共享一致的开发环境。 在描述中提到“官网...

    jemalloc-2.2.5.tar.bz2

    jemalloc-2.2.5

    linux code 2.2.5

    linux code 2.2.5

    AForge .net 最新版 2.2.5

    AForge官网的完整版资源 包括帮助手册+实例+源码 内有 给不方便帆墙的同学用. AForge.NET Framework-2.2.5-(libs only).zip AForge.NET Framework-2.2.5.exe AForge.NET Framework-2.2.5.zip

    webwork2.2.5 jar 文件

    webwork 2.2.5框架资源,大家自由学习.学习框架

    glibc-2.2.5.zip

    《深入剖析Linux内核malloc函数:源于glibc-2.2.5》 在Linux操作系统中,内存管理是系统性能的关键部分,而malloc函数作为C语言标准库中的动态内存分配函数,其工作原理和内部实现至关重要。本文将围绕标题中的...

    vagrant_2.2.5_x86_64.zip

    在本案例中,我们讨论的是Vagrant 2.2.5的x86_64(64位)版本,专为Windows操作系统设计。 Vagrant 使用VirtualBox、VMware或其它虚拟化平台作为后端,但它通过一个简单的命令行界面抽象了这些复杂性。开发者只需要...

    badboy2.2.5 安装包

    **Badboy 2.2.5 安装包详解** Badboy是一款专为JMeter用户设计的辅助工具,尤其在录制和调试HTTP和HTTPS脚本方面表现得极为出色。它作为一个图形化的界面,使得用户能够直观地看到请求和响应的过程,从而更高效地...

    snmp4j-2.2.5.jar

    snmp4j 2.2.5 版本的 snmp4j 2.2.5 版本的 snmp4j 2.2.5 版本的

    Badboy2.2.5.zip

    Badboy是专门录制测试脚本的工具,Badboy录制脚本的方法比较方便易懂,Badboy-2.2.5是最新版可以配合Jmeter使用,快速录制脚本且可以保存为JMeter支持的脚本。badboy测试工具是一个强大WEB测试工具,badboy测试工具...

Global site tag (gtag.js) - Google Analytics