You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by me...@apache.org on 2020/08/03 07:24:53 UTC

[shardingsphere-elasticjob-ui] branch master updated: Remove cloud scheduler dependency

This is an automated email from the ASF dual-hosted git repository.

menghaoran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob-ui.git


The following commit(s) were added to refs/heads/master by this push:
     new 4936142  Remove cloud scheduler dependency
     new eae31a2  Merge pull request #33 from menghaoranss/dev0731
4936142 is described below

commit 49361425af308858ce70ac5615fd84780df2f0a7
Author: menghaoranss <lo...@163.com>
AuthorDate: Mon Aug 3 15:21:40 2020 +0800

    Remove cloud scheduler dependency
---
 pom.xml                                            |   6 +
 .../pom.xml                                        |   6 +-
 .../cloud/ui/config/BeanConfiguration.java         | 108 +-----
 .../cloud/ui/config/EventTraceConfiguration.java   |  55 +++
 .../cloud/ui/config/JobStateConfiguration.java     |  32 ++
 .../cloud/ui/config/RegistryConfiguration.java     |  44 +++
 .../ui/exception/AppConfigurationException.java    |  30 ++
 .../ui/repository/StatisticRdbRepository.java      | 402 +++++++++++++++++++++
 .../elasticjob/cloud/ui/service/FacadeService.java | 309 ++++++++++++++++
 .../cloud/ui/service/RegistryCenterFactory.java    |   2 +
 .../ui/service/app/CloudAppConfiguration.java      |  47 +++
 .../ui/service/app/CloudAppConfigurationNode.java  |  36 ++
 .../service/app/CloudAppConfigurationService.java  |  98 +++++
 .../app/pojo/CloudAppConfigurationPOJO.java        |  71 ++++
 .../ui/service/job/CloudJobConfigurationNode.java  |  36 ++
 .../service/job/CloudJobConfigurationService.java  |  98 +++++
 .../cloud/ui/service/producer/ProducerManager.java |  94 +++++
 .../cloud/ui/service/state/StateNode.java          |  33 ++
 .../service/state/disable/app/DisableAppNode.java  |  37 ++
 .../state/disable/app/DisableAppService.java       |  73 ++++
 .../service/state/disable/job/DisableJobNode.java  |  37 ++
 .../state/disable/job/DisableJobService.java       |  73 ++++
 .../ui/service/state/failover/FailoverNode.java    |  44 +++
 .../ui/service/state/failover/FailoverService.java | 146 ++++++++
 .../service/state/failover/FailoverTaskInfo.java   |  34 ++
 .../cloud/ui/service/state/ready/ReadyNode.java    |  37 ++
 .../cloud/ui/service/state/ready/ReadyService.java | 147 ++++++++
 .../ui/service/state/running/RunningNode.java      |  44 +++
 .../ui/service/state/running/RunningService.java   | 253 +++++++++++++
 .../ui/service/statistics/StatisticManager.java    | 171 +++++++++
 .../ui/service/statistics/TaskResultMetaData.java  |  79 ++++
 .../statistics/util/StatisticTimeUtils.java        |  71 ++++
 .../ui/web/controller/CloudAppController.java      |  55 +--
 .../ui/web/controller/CloudJobController.java      |  16 +-
 .../web/controller/CloudOperationController.java   |  94 -----
 .../src/main/resources/application.properties      |  22 ++
 .../conf/elasticjob-cloud-scheduler.properties     |  62 ----
 .../src/main/resources/application.properties      |  20 +
 .../elasticjob-cloud-scheduler.properties          |  62 ----
 39 files changed, 2716 insertions(+), 368 deletions(-)

diff --git a/pom.xml b/pom.xml
index 749d7f4..9c2d101 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,6 +51,7 @@
         <commons-dbcp2.version>2.2.0</commons-dbcp2.version>
         <h2.version>1.4.196</h2.version>
         <lombok.version>1.16.20</lombok.version>
+        <commons.codec.version>1.10</commons.codec.version>
         <maven.deploy.skip>true</maven.deploy.skip>
     </properties>
     
@@ -179,6 +180,11 @@
                 <version>${lombok.version}</version>
                 <scope>provided</scope>
             </dependency>
+            <dependency>
+                <groupId>commons-codec</groupId>
+                <artifactId>commons-codec</artifactId>
+                <version>${commons.codec.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/pom.xml b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/pom.xml
index 6911e2b..d500bd5 100644
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/pom.xml
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/pom.xml
@@ -29,7 +29,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.shardingsphere.elasticjob</groupId>
-            <artifactId>elasticjob-cloud-scheduler</artifactId>
+            <artifactId>elasticjob-cloud-common</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
@@ -68,6 +68,10 @@
             <groupId>com.h2database</groupId>
             <artifactId>h2</artifactId>
         </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
     </dependencies>
     
     <build>
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/BeanConfiguration.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/BeanConfiguration.java
index 10f2386..95e7571 100644
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/BeanConfiguration.java
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/BeanConfiguration.java
@@ -17,28 +17,13 @@
 
 package org.apache.shardingsphere.elasticjob.cloud.ui.config;
 
-import com.netflix.fenzo.TaskScheduler;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.mesos.MesosSchedulerDriver;
-import org.apache.mesos.Protos;
-import org.apache.mesos.SchedulerDriver;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.app.CloudAppConfigurationService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.job.CloudJobConfigurationService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.env.BootstrapEnvironment;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.env.MesosConfiguration;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.ha.FrameworkIDService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.FacadeService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.MesosStateService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.ReconcileService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.SchedulerEngine;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerManager;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.state.disable.app.DisableAppService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.statistics.StatisticManager;
+import org.apache.shardingsphere.elasticjob.cloud.ui.repository.StatisticRdbRepository;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.controller.search.JobEventRdbSearch;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter;
-import org.apache.shardingsphere.elasticjob.tracing.JobEventBus;
 import org.apache.shardingsphere.elasticjob.tracing.api.TracingConfiguration;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
@@ -49,97 +34,28 @@ import java.util.Optional;
 @Slf4j
 public class BeanConfiguration {
     
-    private static final String WEB_UI_PROTOCOL = "http://";
+    @Autowired
+    private EventTraceConfiguration traceConfiguration;
+    
+    @Autowired
+    private RegistryConfiguration registryConfiguration;
     
     @Bean
     public CoordinatorRegistryCenter regCenter() {
-        CoordinatorRegistryCenter registryCenter = new ZookeeperRegistryCenter(BootstrapEnvironment.getINSTANCE().getZookeeperConfiguration());
+        CoordinatorRegistryCenter registryCenter = new ZookeeperRegistryCenter(registryConfiguration.getZookeeperConfiguration());
         registryCenter.init();
         return registryCenter;
     }
     
     @Bean
-    public CloudAppConfigurationService appConfigService() {
-        return new CloudAppConfigurationService(regCenter());
-    }
-    
-    @Bean
-    public CloudJobConfigurationService jobConfigService() {
-        return new CloudJobConfigurationService(regCenter());
-    }
-    
-    @Bean
-    public MesosStateService mesosStateService() {
-        return new MesosStateService(regCenter());
-    }
-    
-    @Bean
-    public DisableAppService disableAppService() {
-        return new DisableAppService(regCenter());
-    }
-    
-    @Bean
-    public ProducerManager producerManager() {
-        return new ProducerManager(schedulerDriver(), regCenter());
-    }
-    
-    @Bean
-    public FacadeService facadeService() {
-        return new FacadeService(regCenter());
-    }
-    
-    @Bean
-    public StatisticManager statisticManager() {
-        return StatisticManager.getInstance(regCenter(), BootstrapEnvironment.getINSTANCE().getTracingConfiguration().orElse(null));
-    }
-    
-    @Bean
-    public FrameworkIDService frameworkIDService() {
-        return new FrameworkIDService(regCenter());
-    }
-    
-    @Bean
-    public TaskScheduler taskScheduler() {
-        return new TaskScheduler.Builder()
-                .withLeaseOfferExpirySecs(1000000000L)
-                .withLeaseRejectAction(lease -> {
-                    log.warn("Declining offer on '{}'", lease.hostname());
-                    schedulerDriver().declineOffer(lease.getOffer().getId());
-                }).build();
-    }
-    
-    @Bean
-    public JobEventBus jobEventBus() {
-        Optional<TracingConfiguration> tracingConfiguration = BootstrapEnvironment.getINSTANCE().getTracingConfiguration();
-        return tracingConfiguration.map(JobEventBus::new).orElseGet(JobEventBus::new);
-    }
-    
-    @Bean
-    public SchedulerDriver schedulerDriver() {
-        Protos.FrameworkInfo.Builder builder = Protos.FrameworkInfo.newBuilder();
-        frameworkIDService().fetch().ifPresent(frameworkID -> builder.setId(Protos.FrameworkID.newBuilder().setValue(frameworkID).build()));
-        Optional<String> role = BootstrapEnvironment.getINSTANCE().getMesosRole();
-        String frameworkName = MesosConfiguration.FRAMEWORK_NAME;
-        if (role.isPresent()) {
-            builder.setRole(role.get());
-            frameworkName += "-" + role.get();
-        }
-        builder.addCapabilitiesBuilder().setType(Protos.FrameworkInfo.Capability.Type.PARTITION_AWARE);
-        MesosConfiguration mesosConfig = BootstrapEnvironment.getINSTANCE().getMesosConfiguration();
-        Protos.FrameworkInfo frameworkInfo = builder.setUser(mesosConfig.getUser()).setName(frameworkName)
-                .setHostname(mesosConfig.getHostname()).setFailoverTimeout(MesosConfiguration.FRAMEWORK_FAILOVER_TIMEOUT_SECONDS)
-                .setWebuiUrl(WEB_UI_PROTOCOL + BootstrapEnvironment.getINSTANCE().getFrameworkHostPort()).setCheckpoint(true).build();
-        return new MesosSchedulerDriver(new SchedulerEngine(taskScheduler(), facadeService(), jobEventBus(), frameworkIDService(), statisticManager()), frameworkInfo, mesosConfig.getUrl());
+    public StatisticRdbRepository rdbRepository() {
+        Optional<TracingConfiguration> tracingConfiguration = traceConfiguration.getTracingConfiguration();
+        return tracingConfiguration.map(each -> new StatisticRdbRepository((DataSource) each.getStorage(), true)).orElse(new StatisticRdbRepository(null, false));
     }
     
     @Bean
     public JobEventRdbSearch jobEventRdbSearch() {
-        Optional<TracingConfiguration> tracingConfiguration = BootstrapEnvironment.getINSTANCE().getTracingConfiguration();
+        Optional<TracingConfiguration> tracingConfiguration = traceConfiguration.getTracingConfiguration();
         return tracingConfiguration.map(each -> new JobEventRdbSearch((DataSource) each.getStorage(), true)).orElse(new JobEventRdbSearch(null, false));
     }
-    
-    @Bean
-    public ReconcileService reconcileService() {
-        return new ReconcileService(schedulerDriver(), facadeService());
-    }
 }
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/EventTraceConfiguration.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/EventTraceConfiguration.java
new file mode 100644
index 0000000..c0aabe2
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/EventTraceConfiguration.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.config;
+
+import com.google.common.base.Strings;
+import lombok.Setter;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.shardingsphere.elasticjob.tracing.api.TracingConfiguration;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.util.Optional;
+
+@Component
+@ConfigurationProperties(prefix = "event.trace")
+@Setter
+public final class EventTraceConfiguration {
+    
+    private String rdbDriver;
+
+    private String rdbUrl;
+    
+    private String rdbUsername;
+
+    private String rdbPassword;
+    
+    public Optional<TracingConfiguration> getTracingConfiguration() {
+        
+        if (!Strings.isNullOrEmpty(rdbDriver) && !Strings.isNullOrEmpty(rdbUrl) && !Strings.isNullOrEmpty(rdbUsername)) {
+            BasicDataSource dataSource = new BasicDataSource();
+            dataSource.setDriverClassName(rdbDriver);
+            dataSource.setUrl(rdbUrl);
+            dataSource.setUsername(rdbUsername);
+            dataSource.setPassword(rdbPassword);
+            return Optional.of(new TracingConfiguration<DataSource>("RDB", dataSource));
+        }
+        return Optional.empty();
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/JobStateConfiguration.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/JobStateConfiguration.java
new file mode 100644
index 0000000..ddc9abb
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/JobStateConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "job.state")
+@Getter
+@Setter
+public final class JobStateConfiguration {
+    
+    private int queueSize = 10000;
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/RegistryConfiguration.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/RegistryConfiguration.java
new file mode 100644
index 0000000..64af62a
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/config/RegistryConfiguration.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.config;
+
+import com.google.common.base.Strings;
+import lombok.Setter;
+import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperConfiguration;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "zk")
+@Setter
+public final class RegistryConfiguration {
+    
+    private String servers;
+    
+    private String namespace;
+    
+    private String digest;
+    
+    public ZookeeperConfiguration getZookeeperConfiguration() {
+        ZookeeperConfiguration result = new ZookeeperConfiguration(servers, namespace);
+        if (!Strings.isNullOrEmpty(digest)) {
+            result.setDigest(digest);
+        }
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/exception/AppConfigurationException.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/exception/AppConfigurationException.java
new file mode 100644
index 0000000..3fc624f
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/exception/AppConfigurationException.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.exception;
+
+/**
+ * Application configuration exception.
+ */
+public final class AppConfigurationException extends RuntimeException {
+    
+    private static final long serialVersionUID = -1466479389299512371L;
+    
+    public AppConfigurationException(final String errorMessage, final Object... args) {
+        super(String.format(errorMessage, args));
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/repository/StatisticRdbRepository.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/repository/StatisticRdbRepository.java
new file mode 100644
index 0000000..9c1fc96
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/repository/StatisticRdbRepository.java
@@ -0,0 +1,402 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.repository;
+
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.StatisticInterval;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRegisterStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRunningStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskResultStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskRunningStatistics;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Statistic RDB repository.
+ */
+@Slf4j
+public class StatisticRdbRepository {
+    
+    private static final String TABLE_TASK_RESULT_STATISTICS = "TASK_RESULT_STATISTICS";
+    
+    private static final String TABLE_TASK_RUNNING_STATISTICS = "TASK_RUNNING_STATISTICS";
+
+    private static final String TABLE_JOB_RUNNING_STATISTICS = "JOB_RUNNING_STATISTICS";
+    
+    private static final String TABLE_JOB_REGISTER_STATISTICS = "JOB_REGISTER_STATISTICS";
+    
+    private final DataSource dataSource;
+    
+    @Getter
+    private final boolean enable;
+
+    public StatisticRdbRepository(final DataSource dataSource, final boolean enable) {
+        this.dataSource = dataSource;
+        this.enable = enable;
+    }
+
+    /**
+     * Add task result statistics.
+     *
+     * @param taskResultStatistics task result statistics
+     * @return add success or not
+     */
+    public boolean add(final TaskResultStatistics taskResultStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_TASK_RESULT_STATISTICS + "_" + taskResultStatistics.getStatisticInterval()
+                + "` (`success_count`, `failed_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, taskResultStatistics.getSuccessCount());
+            preparedStatement.setInt(2, taskResultStatistics.getFailedCount());
+            preparedStatement.setTimestamp(3, new Timestamp(taskResultStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(4, new Timestamp(taskResultStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert taskResultStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Add task running statistics.
+     *
+     * @param taskRunningStatistics task running statistics
+     * @return add success or not
+     */
+    public boolean add(final TaskRunningStatistics taskRunningStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_TASK_RUNNING_STATISTICS + "` (`running_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, taskRunningStatistics.getRunningCount());
+            preparedStatement.setTimestamp(2, new Timestamp(taskRunningStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(3, new Timestamp(taskRunningStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert taskRunningStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Add job running statistics.
+     *
+     * @param jobRunningStatistics job running statistics
+     * @return add success or not
+     */
+    public boolean add(final JobRunningStatistics jobRunningStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_RUNNING_STATISTICS + "` (`running_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, jobRunningStatistics.getRunningCount());
+            preparedStatement.setTimestamp(2, new Timestamp(jobRunningStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(3, new Timestamp(jobRunningStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert jobRunningStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Add job register statistics.
+     *
+     * @param jobRegisterStatistics job register statistics
+     * @return add success or not
+     */
+    public boolean add(final JobRegisterStatistics jobRegisterStatistics) {
+        boolean result = false;
+        String sql = "INSERT INTO `" + TABLE_JOB_REGISTER_STATISTICS + "` (`registered_count`, `statistics_time`, `creation_time`) VALUES (?, ?, ?);";
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
+            preparedStatement.setInt(1, jobRegisterStatistics.getRegisteredCount());
+            preparedStatement.setTimestamp(2, new Timestamp(jobRegisterStatistics.getStatisticsTime().getTime()));
+            preparedStatement.setTimestamp(3, new Timestamp(jobRegisterStatistics.getCreationTime().getTime()));
+            preparedStatement.execute();
+            result = true;
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Insert jobRegisterStatistics to DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find task result statistics.
+     *
+     * @param from from date to statistics
+     * @param statisticInterval statistic interval
+     * @return task result statistics
+     */
+    public List<TaskResultStatistics> findTaskResultStatistics(final Date from, final StatisticInterval statisticInterval) {
+        List<TaskResultStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, success_count, failed_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                TaskResultStatistics taskResultStatistics = new TaskResultStatistics(resultSet.getLong(1), resultSet.getInt(2), resultSet.getInt(3),
+                        statisticInterval, new Date(resultSet.getTimestamp(4).getTime()), new Date(resultSet.getTimestamp(5).getTime()));
+                result.add(taskResultStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch taskResultStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Get summed task result statistics.
+     *
+     * @param from from date to statistics
+     * @param statisticInterval statistic interval
+     * @return summed task result statistics
+     */
+    public TaskResultStatistics getSummedTaskResultStatistics(final Date from, final StatisticInterval statisticInterval) {
+        TaskResultStatistics result = new TaskResultStatistics(0, 0, statisticInterval, new Date());
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT sum(success_count), sum(failed_count) FROM %s WHERE statistics_time >= '%s'", 
+                TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new TaskResultStatistics(resultSet.getInt(1), resultSet.getInt(2), statisticInterval, new Date());
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch summed taskResultStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find latest task result statistics.
+     *
+     * @param statisticInterval statistic interval
+     * @return task result statistics
+     */
+    public Optional<TaskResultStatistics> findLatestTaskResultStatistics(final StatisticInterval statisticInterval) {
+        TaskResultStatistics result = null;
+        String sql = String.format("SELECT id, success_count, failed_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_TASK_RESULT_STATISTICS + "_" + statisticInterval);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new TaskResultStatistics(resultSet.getLong(1), resultSet.getInt(2), resultSet.getInt(3),
+                        statisticInterval, new Date(resultSet.getTimestamp(4).getTime()), new Date(resultSet.getTimestamp(5).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest taskResultStatistics from DB error:", ex);
+        }
+        return Optional.ofNullable(result);
+    }
+
+    /**
+     * Find task running statistics.
+     *
+     * @param from from date to statistics
+     * @return Task running statistics
+     */
+    public List<TaskRunningStatistics> findTaskRunningStatistics(final Date from) {
+        List<TaskRunningStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_TASK_RUNNING_STATISTICS, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                TaskRunningStatistics taskRunningStatistics = new TaskRunningStatistics(resultSet.getLong(1), resultSet.getInt(2),
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+                result.add(taskRunningStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch taskRunningStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find job running statistics.
+     *
+     * @param from from date to statistics
+     * @return job running statistics
+     */
+    public List<JobRunningStatistics> findJobRunningStatistics(final Date from) {
+        List<JobRunningStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_JOB_RUNNING_STATISTICS, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobRunningStatistics jobRunningStatistics = new JobRunningStatistics(resultSet.getLong(1), resultSet.getInt(2),
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+                result.add(jobRunningStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch jobRunningStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find latest task running statistics.
+     *
+     * @return latest task running statistics
+     */
+    public Optional<TaskRunningStatistics> findLatestTaskRunningStatistics() {
+        TaskRunningStatistics result = null;
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_TASK_RUNNING_STATISTICS);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new TaskRunningStatistics(resultSet.getLong(1), resultSet.getInt(2),
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest taskRunningStatistics from DB error:", ex);
+        }
+        return Optional.ofNullable(result);
+    }
+
+    /**
+     * Find latest job running statistics.
+     *
+     * @return job running statistics
+     */
+    public Optional<JobRunningStatistics> findLatestJobRunningStatistics() {
+        JobRunningStatistics result = null;
+        String sql = String.format("SELECT id, running_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", TABLE_JOB_RUNNING_STATISTICS);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new JobRunningStatistics(resultSet.getLong(1), resultSet.getInt(2),
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest jobRunningStatistics from DB error:", ex);
+        }
+        return Optional.ofNullable(result);
+    }
+
+    /**
+     * Find job register statistics.
+     *
+     * @param from from date to statistics
+     * @return job register statistics
+     */
+    public List<JobRegisterStatistics> findJobRegisterStatistics(final Date from) {
+        List<JobRegisterStatistics> result = new LinkedList<>();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String sql = String.format("SELECT id, registered_count, statistics_time, creation_time FROM %s WHERE statistics_time >= '%s' order by id ASC", 
+                TABLE_JOB_REGISTER_STATISTICS, formatter.format(from));
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                JobRegisterStatistics jobRegisterStatistics = new JobRegisterStatistics(resultSet.getLong(1), resultSet.getInt(2),
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+                result.add(jobRegisterStatistics);
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch jobRegisterStatistics from DB error:", ex);
+        }
+        return result;
+    }
+
+    /**
+     * Find latest job register statistics.
+     *
+     * @return job register statistics
+     */
+    public Optional<JobRegisterStatistics> findLatestJobRegisterStatistics() {
+        JobRegisterStatistics result = null;
+        String sql = String.format("SELECT id, registered_count, statistics_time, creation_time FROM %s order by id DESC LIMIT 1", 
+                TABLE_JOB_REGISTER_STATISTICS);
+        try (
+                Connection conn = dataSource.getConnection();
+                PreparedStatement preparedStatement = conn.prepareStatement(sql);
+                ResultSet resultSet = preparedStatement.executeQuery()
+                ) {
+            while (resultSet.next()) {
+                result = new JobRegisterStatistics(resultSet.getLong(1), resultSet.getInt(2),
+                        new Date(resultSet.getTimestamp(3).getTime()), new Date(resultSet.getTimestamp(4).getTime()));
+            }
+        } catch (final SQLException ex) {
+            // TODO log failure directly to output log, consider to be configurable in the future
+            log.error("Fetch latest jobRegisterStatistics from DB error:", ex);
+        }
+        return Optional.ofNullable(result);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/FacadeService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/FacadeService.java
new file mode 100644
index 0000000..12cc456
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/FacadeService.java
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.CloudAppConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.pojo.CloudAppConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.app.DisableAppService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.job.DisableJobService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.failover.FailoverService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.failover.FailoverTaskInfo;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.ready.ReadyService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.running.RunningService;
+import org.apache.shardingsphere.elasticjob.infra.context.ExecutionType;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Mesos facade service.
+ */
+@Slf4j
+@Service
+public final class FacadeService {
+    
+    @Autowired
+    private CloudAppConfigurationService appConfigService;
+    
+    @Autowired
+    private CloudJobConfigurationService jobConfigService;
+    
+    @Autowired
+    private ReadyService readyService;
+    
+    @Autowired
+    private RunningService runningService;
+    
+    @Autowired
+    private FailoverService failoverService;
+    
+    @Autowired
+    private DisableAppService disableAppService;
+    
+    @Autowired
+    private DisableJobService disableJobService;
+    
+    /**
+     * Start facade service.
+     */
+    public void start() {
+        log.info("Elastic Job: Start facade service");
+        runningService.start();
+    }
+    
+    /**
+     * Remove launched task from queue.
+     *
+     * @param taskContexts task running contexts
+     */
+    public void removeLaunchTasksFromQueue(final List<TaskContext> taskContexts) {
+        List<TaskContext> failoverTaskContexts = new ArrayList<>(taskContexts.size());
+        Collection<String> readyJobNames = new HashSet<>(taskContexts.size(), 1);
+        for (TaskContext each : taskContexts) {
+            switch (each.getType()) {
+                case FAILOVER:
+                    failoverTaskContexts.add(each);
+                    break;
+                case READY:
+                    readyJobNames.add(each.getMetaInfo().getJobName());
+                    break;
+                default:
+                    break;
+            }
+        }
+        failoverService.remove(failoverTaskContexts.stream().map(TaskContext::getMetaInfo).collect(Collectors.toList()));
+        readyService.remove(readyJobNames);
+    }
+    
+    /**
+     * Add task to running queue.
+     *
+     * @param taskContext task running context
+     */
+    public void addRunning(final TaskContext taskContext) {
+        runningService.add(taskContext);
+    }
+    
+    /**
+     * Update daemon task status.
+     *
+     * @param taskContext task running context
+     * @param isIdle set to idle or not
+     */
+    public void updateDaemonStatus(final TaskContext taskContext, final boolean isIdle) {
+        runningService.updateIdle(taskContext, isIdle);
+    }
+    
+    /**
+     * Remove task from running queue.
+     *
+     * @param taskContext task running context
+     */
+    public void removeRunning(final TaskContext taskContext) {
+        runningService.remove(taskContext);
+    }
+    
+    /**
+     * Record task to failover queue.
+     *
+     * @param taskContext task running context
+     */
+    public void recordFailoverTask(final TaskContext taskContext) {
+        Optional<CloudJobConfigurationPOJO> cloudJobConfigOptional = jobConfigService.load(taskContext.getMetaInfo().getJobName());
+        if (!cloudJobConfigOptional.isPresent()) {
+            return;
+        }
+        if (isDisable(cloudJobConfigOptional.get())) {
+            return;
+        }
+        CloudJobConfigurationPOJO cloudJobConfig = cloudJobConfigOptional.get();
+        if (cloudJobConfig.isFailover() || CloudJobExecutionType.DAEMON == cloudJobConfig.getJobExecutionType()) {
+            failoverService.add(taskContext);
+        }
+    }
+    
+    private boolean isDisable(final CloudJobConfigurationPOJO cloudJobConfig) {
+        return disableAppService.isDisabled(cloudJobConfig.getAppName()) || disableJobService.isDisabled(cloudJobConfig.getJobName());
+    }
+    
+    /**
+     * Add transient job to ready queue.
+     *
+     * @param jobName job name
+     */
+    public void addTransient(final String jobName) {
+        readyService.addTransient(jobName);
+    }
+    
+    /**
+     * Load cloud job config.
+     *
+     * @param jobName job name
+     * @return cloud job config
+     */
+    public Optional<CloudJobConfigurationPOJO> load(final String jobName) {
+        return jobConfigService.load(jobName);
+    }
+    
+    /**
+     * Load app config by app name.
+     *
+     * @param appName app name
+     * @return cloud app config
+     */
+    public Optional<CloudAppConfigurationPOJO> loadAppConfig(final String appName) {
+        return appConfigService.load(appName);
+    }
+    
+    /**
+     * Get failover task id by task meta info.
+     *
+     * @param metaInfo task meta info
+     * @return failover task id
+     */
+    public Optional<String> getFailoverTaskId(final MetaInfo metaInfo) {
+        return failoverService.getTaskId(metaInfo);
+    }
+    
+    /**
+     * Add daemon job to ready queue.
+     *
+     * @param jobName job name
+     */
+    public void addDaemonJobToReadyQueue(final String jobName) {
+        Optional<CloudJobConfigurationPOJO> cloudJobConfig = jobConfigService.load(jobName);
+        if (!cloudJobConfig.isPresent()) {
+            return;
+        }
+        if (isDisable(cloudJobConfig.get())) {
+            return;
+        }
+        readyService.addDaemon(jobName);
+    }
+    
+    /**
+     * Determine whether the task is running or not.
+     *
+     * @param taskContext task running context
+     * @return true is running, otherwise not
+     */
+    public boolean isRunning(final TaskContext taskContext) {
+        return ExecutionType.FAILOVER != taskContext.getType() && !runningService.getRunningTasks(taskContext.getMetaInfo().getJobName()).isEmpty()
+                || ExecutionType.FAILOVER == taskContext.getType() && runningService.isTaskRunning(taskContext.getMetaInfo());
+    }
+    
+    /**
+     * Add mapping of the task primary key and host name.
+     *
+     * @param taskId task primary key
+     * @param hostname host name
+     */
+    public void addMapping(final String taskId, final String hostname) {
+        runningService.addMapping(taskId, hostname);
+    }
+    
+    /**
+     * Retrieve hostname and then remove task.
+     *
+     * @param taskId task primary key
+     * @return hostname of the removed task
+     */
+    public String popMapping(final String taskId) {
+        return runningService.popMapping(taskId);
+    }
+    
+    /**
+     * Get all ready tasks.
+     *
+     * @return ready tasks
+     */
+    public Map<String, Integer> getAllReadyTasks() {
+        return readyService.getAllReadyTasks();
+    }
+    
+    /**
+     * Get all running tasks.
+     *
+     * @return running tasks
+     */
+    public Map<String, Set<TaskContext>> getAllRunningTasks() {
+        return runningService.getAllRunningTasks();
+    }
+    
+    /**
+     * Get all failover tasks.
+     *
+     * @return failover tasks
+     */
+    public Map<String, Collection<FailoverTaskInfo>> getAllFailoverTasks() {
+        return failoverService.getAllFailoverTasks();
+    }
+    
+    /**
+     * Determine whether the job is disable or not.
+     *
+     * @param jobName job name
+     * @return true is disabled, otherwise not
+     */
+    public boolean isJobDisabled(final String jobName) {
+        Optional<CloudJobConfigurationPOJO> jobConfiguration = jobConfigService.load(jobName);
+        return !jobConfiguration.isPresent() || disableAppService.isDisabled(jobConfiguration.get().getAppName()) || disableJobService.isDisabled(jobName);
+    }
+    
+    /**
+     * Enable job.
+     *
+     * @param jobName job name
+     */
+    public void enableJob(final String jobName) {
+        disableJobService.remove(jobName);
+    }
+    
+    /**
+     * Disable job.
+     *
+     * @param jobName job name
+     */
+    public void disableJob(final String jobName) {
+        disableJobService.add(jobName);
+    }
+    
+    
+    /**
+     * Stop facade service.
+     */
+    public void stop() {
+        log.info("Elastic Job: Stop facade service");
+        // TODO stop scheduler
+        runningService.clear();
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/RegistryCenterFactory.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/RegistryCenterFactory.java
index 22755be..c45cc8b 100644
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/RegistryCenterFactory.java
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/RegistryCenterFactory.java
@@ -24,6 +24,8 @@ import com.google.common.hash.Hasher;
 import com.google.common.hash.Hashing;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.domain.RegistryCenterConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.ui.util.SessionRegistryCenterConfiguration;
 import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
 import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperConfiguration;
 import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter;
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfiguration.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfiguration.java
new file mode 100644
index 0000000..0540821
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfiguration.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.app;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+/**
+ * Cloud app configuration.
+ */
+@AllArgsConstructor
+@RequiredArgsConstructor
+@Getter
+@ToString
+public final class CloudAppConfiguration {
+    
+    private final String appName;
+    
+    private final String appURL;
+    
+    private final String bootstrapScript;
+    
+    private double cpuCount = 1d;
+    
+    private double memoryMB = 128d;
+    
+    private boolean appCacheEnable = true;
+    
+    private int eventTraceSamplingCount;
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfigurationNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfigurationNode.java
new file mode 100644
index 0000000..2a48ce0
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfigurationNode.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.app;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * Cloud app configuration node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class CloudAppConfigurationNode {
+    
+    public static final String ROOT = "/config/app";
+    
+    private static final String APP_CONFIG = ROOT + "/%s";
+    
+    static String getRootNodePath(final String appName) {
+        return String.format(APP_CONFIG, appName);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfigurationService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfigurationService.java
new file mode 100644
index 0000000..afe1dba
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/CloudAppConfigurationService.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.app;
+
+import com.google.common.base.Strings;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.pojo.CloudAppConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Cloud app configuration service.
+ */
+@Service("appConfigService")
+public final class CloudAppConfigurationService {
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    /**
+     * Add cloud app configuration.
+     *
+     * @param appConfig cloud app configuration
+     */
+    public void add(final CloudAppConfigurationPOJO appConfig) {
+        regCenter.persist(CloudAppConfigurationNode.getRootNodePath(appConfig.getAppName()), YamlEngine.marshal(appConfig));
+    }
+    
+    /**
+     * Update cloud app configuration.
+     *
+     * @param appConfig cloud app configuration
+     */
+    public void update(final CloudAppConfigurationPOJO appConfig) {
+        regCenter.update(CloudAppConfigurationNode.getRootNodePath(appConfig.getAppName()), YamlEngine.marshal(appConfig));
+    }
+    
+    /**
+     * Load app configuration by app name.
+     *
+     * @param appName application name
+     * @return cloud app configuration
+     */
+    public Optional<CloudAppConfigurationPOJO> load(final String appName) {
+        String configContent = regCenter.get(CloudAppConfigurationNode.getRootNodePath(appName));
+        return Strings.isNullOrEmpty(configContent) ? Optional.empty() : Optional.of(YamlEngine.unmarshal(configContent, CloudAppConfigurationPOJO.class));
+    }
+    
+    /**
+     * Load all registered cloud app configurations.
+     *
+     * @return collection of the registered cloud app configuration
+     */
+    public Collection<CloudAppConfigurationPOJO> loadAll() {
+        if (!regCenter.isExisted(CloudAppConfigurationNode.ROOT)) {
+            return Collections.emptyList();
+        }
+        List<String> appNames = regCenter.getChildrenKeys(CloudAppConfigurationNode.ROOT);
+        Collection<CloudAppConfigurationPOJO> result = new ArrayList<>(appNames.size());
+        for (String each : appNames) {
+            Optional<CloudAppConfigurationPOJO> config = load(each);
+            config.ifPresent(result::add);
+        }
+        return result;
+    }
+    
+    /**
+     * Remove cloud app configuration by app name.
+     *
+     * @param appName to be removed application name
+     */
+    public void remove(final String appName) {
+        regCenter.remove(CloudAppConfigurationNode.getRootNodePath(appName));
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/pojo/CloudAppConfigurationPOJO.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/pojo/CloudAppConfigurationPOJO.java
new file mode 100644
index 0000000..aa007f6
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/app/pojo/CloudAppConfigurationPOJO.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.app.pojo;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.CloudAppConfiguration;
+
+/**
+ * Cloud app configuration POJO.
+ */
+@Getter
+@Setter
+public final class CloudAppConfigurationPOJO {
+    
+    private String appName;
+    
+    private String appURL;
+    
+    private String bootstrapScript;
+    
+    private double cpuCount = 1d;
+    
+    private double memoryMB = 128d;
+    
+    private boolean appCacheEnable = true;
+    
+    private int eventTraceSamplingCount;
+    
+    /**
+     * Convert to cloud app configuration.
+     *
+     * @return cloud app configuration
+     */
+    public CloudAppConfiguration toCloudAppConfiguration() {
+        return new CloudAppConfiguration(appName, appURL, bootstrapScript, cpuCount, memoryMB, appCacheEnable, eventTraceSamplingCount);
+    }
+    
+    /**
+     * Convert from cloud app configuration.
+     *
+     * @param cloudAppConfig cloud job configuration
+     * @return cloud app configuration POJO
+     */
+    public static CloudAppConfigurationPOJO fromCloudAppConfiguration(final CloudAppConfiguration cloudAppConfig) {
+        CloudAppConfigurationPOJO result = new CloudAppConfigurationPOJO();
+        result.setAppName(cloudAppConfig.getAppName());
+        result.setAppURL(cloudAppConfig.getAppURL());
+        result.setBootstrapScript(cloudAppConfig.getBootstrapScript());
+        result.setCpuCount(cloudAppConfig.getCpuCount());
+        result.setMemoryMB(cloudAppConfig.getMemoryMB());
+        result.setAppCacheEnable(cloudAppConfig.isAppCacheEnable());
+        result.setEventTraceSamplingCount(cloudAppConfig.getEventTraceSamplingCount());
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/job/CloudJobConfigurationNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/job/CloudJobConfigurationNode.java
new file mode 100644
index 0000000..01f2944
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/job/CloudJobConfigurationNode.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.job;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * Cloud job configuration node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class CloudJobConfigurationNode {
+    
+    public static final String ROOT = "/config/job";
+    
+    private static final String JOB_CONFIG = ROOT + "/%s";
+    
+    static String getRootNodePath(final String jobName) {
+        return String.format(JOB_CONFIG, jobName);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/job/CloudJobConfigurationService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/job/CloudJobConfigurationService.java
new file mode 100644
index 0000000..11ecc33
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/job/CloudJobConfigurationService.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.job;
+
+import com.google.common.base.Strings;
+import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.infra.yaml.YamlEngine;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Cloud job configuration service.
+ */
+@Service
+public final class CloudJobConfigurationService {
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    /**
+     * Add cloud job configuration.
+     * 
+     * @param cloudJobConfig cloud job configuration
+     */
+    public void add(final CloudJobConfigurationPOJO cloudJobConfig) {
+        regCenter.persist(
+                CloudJobConfigurationNode.getRootNodePath(cloudJobConfig.getJobName()), YamlEngine.marshal(cloudJobConfig));
+    }
+    
+    /**
+     * Update cloud job configuration.
+     *
+     * @param cloudJobConfig cloud job configuration
+     */
+    public void update(final CloudJobConfigurationPOJO cloudJobConfig) {
+        regCenter.update(
+                CloudJobConfigurationNode.getRootNodePath(cloudJobConfig.getJobName()), YamlEngine.marshal(cloudJobConfig));
+    }
+    
+    /**
+     * Load all registered cloud job configurations.
+     *
+     * @return collection of the registered cloud job configuration
+     */
+    public Collection<CloudJobConfigurationPOJO> loadAll() {
+        if (!regCenter.isExisted(CloudJobConfigurationNode.ROOT)) {
+            return Collections.emptyList();
+        }
+        List<String> jobNames = regCenter.getChildrenKeys(CloudJobConfigurationNode.ROOT);
+        Collection<CloudJobConfigurationPOJO> result = new ArrayList<>(jobNames.size());
+        for (String each : jobNames) {
+            load(each).ifPresent(result::add);
+        }
+        return result;
+    }
+    
+    /**
+     * Load cloud job configuration by job name.
+     *
+     * @param jobName job name
+     * @return cloud job configuration
+     */
+    public Optional<CloudJobConfigurationPOJO> load(final String jobName) {
+        String configContent = regCenter.get(CloudJobConfigurationNode.getRootNodePath(jobName));
+        return Strings.isNullOrEmpty(configContent) ? Optional.empty() : Optional.of(YamlEngine.unmarshal(configContent, CloudJobConfigurationPOJO.class));
+    }
+    
+    /**
+     * Remove cloud job configuration.
+     *
+     * @param jobName job name
+     */
+    public void remove(final String jobName) {
+        regCenter.remove(CloudJobConfigurationNode.getRootNodePath(jobName));
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/producer/ProducerManager.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/producer/ProducerManager.java
new file mode 100644
index 0000000..21ae5c3
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/producer/ProducerManager.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.producer;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.exception.AppConfigurationException;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.CloudAppConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.pojo.CloudAppConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.job.DisableJobService;
+import org.apache.shardingsphere.elasticjob.infra.exception.JobConfigurationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+/**
+ * Producer manager.
+ */
+@Slf4j
+@Service
+public final class ProducerManager {
+    
+    @Autowired
+    private CloudAppConfigurationService appConfigService;
+    
+    @Autowired
+    private CloudJobConfigurationService configService;
+    
+    @Autowired
+    private DisableJobService disableJobService;
+    
+    /**
+     * Register the job.
+     * 
+     * @param cloudJobConfig cloud job configuration
+     */
+    public void register(final CloudJobConfigurationPOJO cloudJobConfig) {
+        if (disableJobService.isDisabled(cloudJobConfig.getJobName())) {
+            throw new JobConfigurationException("Job '%s' has been disable.", cloudJobConfig.getJobName());
+        }
+        Optional<CloudAppConfigurationPOJO> appConfigFromZk = appConfigService.load(cloudJobConfig.getAppName());
+        if (!appConfigFromZk.isPresent()) {
+            throw new AppConfigurationException("Register app '%s' firstly.", cloudJobConfig.getAppName());
+        }
+        Optional<CloudJobConfigurationPOJO> jobConfigFromZk = configService.load(cloudJobConfig.getJobName());
+        if (jobConfigFromZk.isPresent()) {
+            throw new JobConfigurationException("Job '%s' already existed.", cloudJobConfig.getJobName());
+        }
+        configService.add(cloudJobConfig);
+    }
+    
+    /**
+     * Update the job.
+     *
+     * @param cloudJobConfig cloud job configuration
+     */
+    public void update(final CloudJobConfigurationPOJO cloudJobConfig) {
+        Optional<CloudJobConfigurationPOJO> jobConfigFromZk = configService.load(cloudJobConfig.getJobName());
+        if (!jobConfigFromZk.isPresent()) {
+            throw new JobConfigurationException("Cannot found job '%s', please register first.", cloudJobConfig.getJobName());
+        }
+        configService.update(cloudJobConfig);
+    }
+    
+    /**
+     * Deregister the job.
+     * 
+     * @param jobName job name
+     */
+    public void deregister(final String jobName) {
+        Optional<CloudJobConfigurationPOJO> jobConfig = configService.load(jobName);
+        if (jobConfig.isPresent()) {
+            disableJobService.remove(jobName);
+            configService.remove(jobName);
+        }
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/StateNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/StateNode.java
new file mode 100644
index 0000000..218c1e1
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/StateNode.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * State node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class StateNode {
+    
+    /**
+     * Root state node.
+     */
+    public static final String ROOT = "/state";
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/app/DisableAppNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/app/DisableAppNode.java
new file mode 100644
index 0000000..4c7b13e
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/app/DisableAppNode.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.app;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.StateNode;
+
+/**
+ * Disable app node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+final class DisableAppNode {
+    
+    static final String ROOT = StateNode.ROOT + "/disable/app";
+    
+    private static final String DISABLE_APP = ROOT + "/%s";
+    
+    static String getDisableAppNodePath(final String appName) {
+        return String.format(DISABLE_APP, appName);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/app/DisableAppService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/app/DisableAppService.java
new file mode 100644
index 0000000..3e7d884
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/app/DisableAppService.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.app;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.ui.config.JobStateConfiguration;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Disable app service.
+ */
+@Slf4j
+@Service
+public class DisableAppService {
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    @Autowired
+    private JobStateConfiguration jobStateConfiguration;
+    
+    /**
+     * Add application name to disable queue.
+     *
+     * @param appName application name
+     */
+    public void add(final String appName) {
+        if (regCenter.getNumChildren(DisableAppNode.ROOT) > jobStateConfiguration.getQueueSize()) {
+            log.warn("Cannot add disable app, caused by read state queue size is larger than {}.", jobStateConfiguration.getQueueSize());
+            return;
+        }
+        String disableAppNodePath = DisableAppNode.getDisableAppNodePath(appName);
+        if (!regCenter.isExisted(disableAppNodePath)) {
+            regCenter.persist(disableAppNodePath, appName);
+        }
+    }
+    
+    /**
+     * Remove application name from disable queue.
+     *
+     * @param appName application name
+     */
+    public void remove(final String appName) {
+        regCenter.remove(DisableAppNode.getDisableAppNodePath(appName));
+    }
+    
+    /**
+     * Check whether the application name is disabled or not.
+     *
+     * @param appName application name
+     * @return true is in the disable queue, otherwise not
+     */
+    public boolean isDisabled(final String appName) {
+        return regCenter.isExisted(DisableAppNode.getDisableAppNodePath(appName));
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/job/DisableJobNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/job/DisableJobNode.java
new file mode 100644
index 0000000..fdd7eab
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/job/DisableJobNode.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.job;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.StateNode;
+
+/**
+ * Disable job node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+final class DisableJobNode {
+    
+    static final String ROOT = StateNode.ROOT + "/disable/job";
+    
+    private static final String DISABLE_JOB = ROOT + "/%s";
+    
+    static String getDisableJobNodePath(final String jobName) {
+        return String.format(DISABLE_JOB, jobName);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/job/DisableJobService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/job/DisableJobService.java
new file mode 100644
index 0000000..9e1cee8
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/disable/job/DisableJobService.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.job;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.ui.config.JobStateConfiguration;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Disable job service.
+ */
+@Slf4j
+@Service
+public class DisableJobService {
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    @Autowired
+    private JobStateConfiguration jobStateConfiguration;
+    
+    /**
+     * Add job to the disable queue.
+     *
+     * @param jobName job name
+     */
+    public void add(final String jobName) {
+        if (regCenter.getNumChildren(DisableJobNode.ROOT) > jobStateConfiguration.getQueueSize()) {
+            log.warn("Cannot add disable job, caused by read state queue size is larger than {}.", jobStateConfiguration.getQueueSize());
+            return;
+        }
+        String disableJobNodePath = DisableJobNode.getDisableJobNodePath(jobName);
+        if (!regCenter.isExisted(disableJobNodePath)) {
+            regCenter.persist(disableJobNodePath, jobName);
+        }
+    }
+    
+    /**
+     * Remove the job from the disable queue.
+     *
+     * @param jobName job name
+     */
+    public void remove(final String jobName) {
+        regCenter.remove(DisableJobNode.getDisableJobNodePath(jobName));
+    }
+    
+    /**
+     * Determine whether the job is in the disable queue or not.
+     *
+     * @param jobName job name
+     * @return true is in the disable queue, otherwise not
+     */
+    public boolean isDisabled(final String jobName) {
+        return regCenter.isExisted(DisableJobNode.getDisableJobNodePath(jobName));
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverNode.java
new file mode 100644
index 0000000..002f07a
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverNode.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.failover;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.StateNode;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
+
+/**
+ * Failover node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+final class FailoverNode {
+    
+    static final String ROOT = StateNode.ROOT + "/failover";
+    
+    private static final String FAILOVER_JOB = ROOT + "/%s";
+    
+    private static final String FAILOVER_TASK = FAILOVER_JOB + "/%s";
+    
+    static String getFailoverJobNodePath(final String jobName) {
+        return String.format(FAILOVER_JOB, jobName);
+    }
+    
+    static String getFailoverTaskNodePath(final String taskMetaInfo) {
+        return String.format(FAILOVER_TASK, MetaInfo.from(taskMetaInfo).getJobName(), taskMetaInfo);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverService.java
new file mode 100644
index 0000000..b98d8ed
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverService.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.failover;
+
+import com.google.common.base.Strings;
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hashing;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.ui.config.JobStateConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.running.RunningService;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Failover service.
+ */
+@Slf4j
+@Service
+public final class FailoverService {
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    @Autowired
+    private RunningService runningService;
+    
+    @Autowired
+    private JobStateConfiguration jobStateConfiguration;
+    
+    /**
+     * Add task to failover queue.
+     *
+     * @param taskContext task running context
+     */
+    public void add(final TaskContext taskContext) {
+        if (regCenter.getNumChildren(FailoverNode.ROOT) > jobStateConfiguration.getQueueSize()) {
+            log.warn("Cannot add job, caused by read state queue size is larger than {}.", jobStateConfiguration.getQueueSize());
+            return;
+        }
+        String failoverTaskNodePath = FailoverNode.getFailoverTaskNodePath(taskContext.getMetaInfo().toString());
+        if (!regCenter.isExisted(failoverTaskNodePath) && !runningService.isTaskRunning(taskContext.getMetaInfo())) {
+            // TODO Whether Daemon-type jobs increase storage and fail immediately?
+            regCenter.persist(failoverTaskNodePath, taskContext.getId());
+        }
+    }
+    
+    private List<Integer> getAssignedShardingItems(final String jobName, final List<String> taskIdList, final Set<HashCode> assignedTasks) {
+        List<Integer> result = new ArrayList<>(taskIdList.size());
+        for (String each : taskIdList) {
+            MetaInfo metaInfo = MetaInfo.from(each);
+            if (assignedTasks.add(Hashing.sha256().newHasher().putString(jobName, StandardCharsets.UTF_8).putInt(metaInfo.getShardingItems().get(0)).hash())
+                    && !runningService.isTaskRunning(metaInfo)) {
+                result.add(metaInfo.getShardingItems().get(0));
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Remove task from the failover queue.
+     *
+     * @param metaInfoList collection of task meta infos to be removed
+     */
+    public void remove(final Collection<MetaInfo> metaInfoList) {
+        for (MetaInfo each : metaInfoList) {
+            regCenter.remove(FailoverNode.getFailoverTaskNodePath(each.toString()));
+        }
+    }
+    
+    /**
+     * Get task id from failover queue.
+     *
+     * @param metaInfo task meta info
+     * @return failover task id
+     */
+    public Optional<String> getTaskId(final MetaInfo metaInfo) {
+        String failoverTaskNodePath = FailoverNode.getFailoverTaskNodePath(metaInfo.toString());
+        return regCenter.isExisted(failoverTaskNodePath) ? Optional.of(regCenter.get(failoverTaskNodePath)) : Optional.empty();
+    }
+    
+    /**
+     * Get all failover tasks.
+     *
+     * @return all failover tasks
+     */
+    public Map<String, Collection<FailoverTaskInfo>> getAllFailoverTasks() {
+        if (!regCenter.isExisted(FailoverNode.ROOT)) {
+            return Collections.emptyMap();
+        }
+        List<String> jobNames = regCenter.getChildrenKeys(FailoverNode.ROOT);
+        Map<String, Collection<FailoverTaskInfo>> result = new HashMap<>(jobNames.size(), 1);
+        for (String each : jobNames) {
+            Collection<FailoverTaskInfo> failoverTasks = getFailoverTasks(each);
+            if (!failoverTasks.isEmpty()) {
+                result.put(each, failoverTasks);
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Get failover tasks.
+     *
+     * @param jobName job name
+     * @return collection of failover tasks
+     */
+    private Collection<FailoverTaskInfo> getFailoverTasks(final String jobName) {
+        List<String> failOverTasks = regCenter.getChildrenKeys(FailoverNode.getFailoverJobNodePath(jobName));
+        List<FailoverTaskInfo> result = new ArrayList<>(failOverTasks.size());
+        for (String each : failOverTasks) {
+            String originalTaskId = regCenter.get(FailoverNode.getFailoverTaskNodePath(each));
+            if (!Strings.isNullOrEmpty(originalTaskId)) {
+                result.add(new FailoverTaskInfo(MetaInfo.from(each), originalTaskId));
+            }
+        }
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverTaskInfo.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverTaskInfo.java
new file mode 100644
index 0000000..77641f3
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/failover/FailoverTaskInfo.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.failover;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
+
+/**
+ * Failover task info.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class FailoverTaskInfo {
+    
+    private final MetaInfo taskInfo;
+    
+    private final String originalTaskId;
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/ready/ReadyNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/ready/ReadyNode.java
new file mode 100644
index 0000000..ea0aceb
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/ready/ReadyNode.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.ready;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.StateNode;
+
+/**
+ * Ready node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+final class ReadyNode {
+    
+    static final String ROOT = StateNode.ROOT + "/ready";
+    
+    private static final String READY_JOB = ROOT + "/%s";
+    
+    static String getReadyJobNodePath(final String jobName) {
+        return String.format(READY_JOB, jobName);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/ready/ReadyService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/ready/ReadyService.java
new file mode 100644
index 0000000..b5544a6
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/ready/ReadyService.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.ready;
+
+import com.google.common.base.Strings;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.config.JobStateConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.running.RunningService;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Ready service.
+ */
+@Slf4j
+@Service
+public final class ReadyService {
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    @Autowired
+    private CloudJobConfigurationService configService;
+    
+    @Autowired
+    private RunningService runningService;
+    
+    @Autowired
+    private JobStateConfiguration jobStateConfiguration;
+    
+    
+    /**
+     * Add transient job to ready queue.
+     * 
+     * @param jobName job name
+     */
+    public void addTransient(final String jobName) {
+        if (regCenter.getNumChildren(ReadyNode.ROOT) > jobStateConfiguration.getQueueSize()) {
+            log.warn("Cannot add transient job, caused by read state queue size is larger than {}.", jobStateConfiguration.getQueueSize());
+            return;
+        }
+        Optional<CloudJobConfigurationPOJO> cloudJobConfig = configService.load(jobName);
+        if (!cloudJobConfig.isPresent() || CloudJobExecutionType.TRANSIENT != cloudJobConfig.get().getJobExecutionType()) {
+            return;
+        }
+        String readyJobNode = ReadyNode.getReadyJobNodePath(jobName);
+        String times = regCenter.getDirectly(readyJobNode);
+        if (cloudJobConfig.get().isMisfire()) {
+            regCenter.persist(readyJobNode, Integer.toString(null == times ? 1 : Integer.parseInt(times) + 1));
+        } else {
+            regCenter.persist(ReadyNode.getReadyJobNodePath(jobName), "1");
+        }
+    }
+    
+    /**
+     * Add daemon job to ready queue.
+     *
+     * @param jobName job name
+     */
+    public void addDaemon(final String jobName) {
+        if (regCenter.getNumChildren(ReadyNode.ROOT) > jobStateConfiguration.getQueueSize()) {
+            log.warn("Cannot add daemon job, caused by read state queue size is larger than {}.", jobStateConfiguration.getQueueSize());
+            return;
+        }
+        Optional<CloudJobConfigurationPOJO> cloudJobConfig = configService.load(jobName);
+        if (!cloudJobConfig.isPresent() || CloudJobExecutionType.DAEMON != cloudJobConfig.get().getJobExecutionType() || runningService.isJobRunning(jobName)) {
+            return;
+        }
+        regCenter.persist(ReadyNode.getReadyJobNodePath(jobName), "1");
+    }
+    
+    /**
+     * Set misfire disabled.
+     * 
+     * @param jobName job name
+     */
+    public void setMisfireDisabled(final String jobName) {
+        Optional<CloudJobConfigurationPOJO> cloudJobConfig = configService.load(jobName);
+        if (cloudJobConfig.isPresent() && null != regCenter.getDirectly(ReadyNode.getReadyJobNodePath(jobName))) {
+            regCenter.persist(ReadyNode.getReadyJobNodePath(jobName), "1");
+        }
+    }
+    
+    /**
+     * Remove jobs from ready queue.
+     *
+     * @param jobNames collection of jobs to be removed
+     */
+    public void remove(final Collection<String> jobNames) {
+        for (String each : jobNames) {
+            String readyJobNode = ReadyNode.getReadyJobNodePath(each);
+            String timesStr = regCenter.getDirectly(readyJobNode);
+            int times = null == timesStr ? 0 : Integer.parseInt(timesStr);
+            if (times <= 1) {
+                regCenter.remove(readyJobNode);
+            } else {
+                regCenter.persist(readyJobNode, Integer.toString(times - 1));
+            }
+        }
+    }
+    
+    /**
+     * Get all ready tasks.
+     * 
+     * @return all ready tasks
+     */
+    public Map<String, Integer> getAllReadyTasks() {
+        if (!regCenter.isExisted(ReadyNode.ROOT)) {
+            return Collections.emptyMap();
+        }
+        List<String> jobNames = regCenter.getChildrenKeys(ReadyNode.ROOT);
+        Map<String, Integer> result = new HashMap<>(jobNames.size(), 1);
+        for (String each : jobNames) {
+            String times = regCenter.get(ReadyNode.getReadyJobNodePath(each));
+            if (!Strings.isNullOrEmpty(times)) {
+                result.put(each, Integer.parseInt(times));
+            }
+        }
+        return result;
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/running/RunningNode.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/running/RunningNode.java
new file mode 100644
index 0000000..9d0d8c8
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/running/RunningNode.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.running;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.StateNode;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
+
+/**
+ * Running node.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+final class RunningNode {
+    
+    static final String ROOT = StateNode.ROOT + "/running";
+    
+    private static final String RUNNING_JOB = ROOT + "/%s";
+    
+    private static final String RUNNING_TASK = RUNNING_JOB + "/%s";
+    
+    static String getRunningJobNodePath(final String jobName) {
+        return String.format(RUNNING_JOB, jobName);
+    }
+    
+    static String getRunningTaskNodePath(final String taskMetaInfo) {
+        return String.format(RUNNING_TASK, MetaInfo.from(taskMetaInfo).getJobName(), taskMetaInfo);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/running/RunningService.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/running/RunningService.java
new file mode 100644
index 0000000..7de20fc
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/state/running/RunningService.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.state.running;
+
+import com.google.common.collect.Sets;
+import lombok.Getter;
+import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext;
+import org.apache.shardingsphere.elasticjob.infra.context.TaskContext.MetaInfo;
+import org.apache.shardingsphere.elasticjob.reg.base.CoordinatorRegistryCenter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.stream.Collectors;
+
+/**
+ * Running service.
+ */
+@Service
+public final class RunningService {
+    
+    private static final int TASK_INITIAL_SIZE = 1024;
+    
+    // TODO Using JMX to export
+    @Getter
+    private static final ConcurrentHashMap<String, Set<TaskContext>> RUNNING_TASKS = new ConcurrentHashMap<>(TASK_INITIAL_SIZE);
+    
+    private static final ConcurrentHashMap<String, String> TASK_HOSTNAME_MAPPER = new ConcurrentHashMap<>(TASK_INITIAL_SIZE);
+    
+    @Autowired
+    private CoordinatorRegistryCenter regCenter;
+    
+    @Autowired
+    private CloudJobConfigurationService configurationService;
+    
+    /**
+     * Start running queue service.
+     */
+    public void start() {
+        clear();
+        List<String> jobKeys = regCenter.getChildrenKeys(RunningNode.ROOT);
+        for (String each : jobKeys) {
+            if (!configurationService.load(each).isPresent()) {
+                remove(each);
+                continue;
+            }
+            RUNNING_TASKS.put(each, Sets.newCopyOnWriteArraySet(regCenter.getChildrenKeys(RunningNode.getRunningJobNodePath(each)).stream().map(
+                input -> TaskContext.from(regCenter.get(RunningNode.getRunningTaskNodePath(MetaInfo.from(input).toString())))).collect(Collectors.toList())));
+        }
+    }
+    
+    /**
+     * Add task to running queue.
+     * 
+     * @param taskContext task running context
+     */
+    public void add(final TaskContext taskContext) {
+        if (!configurationService.load(taskContext.getMetaInfo().getJobName()).isPresent()) {
+            return;
+        }
+        getRunningTasks(taskContext.getMetaInfo().getJobName()).add(taskContext);
+        if (!isDaemon(taskContext.getMetaInfo().getJobName())) {
+            return;
+        }
+        String runningTaskNodePath = RunningNode.getRunningTaskNodePath(taskContext.getMetaInfo().toString());
+        if (!regCenter.isExisted(runningTaskNodePath)) {
+            regCenter.persist(runningTaskNodePath, taskContext.getId());
+        }
+    }
+    
+    private boolean isDaemon(final String jobName) {
+        Optional<CloudJobConfigurationPOJO> cloudJobConfig = configurationService.load(jobName);
+        return cloudJobConfig.isPresent() && CloudJobExecutionType.DAEMON == cloudJobConfig.get().getJobExecutionType();
+    }
+    
+    /**
+     * Update task to idle state.
+     *
+     * @param taskContext task running context
+     * @param isIdle is idle
+     */
+    public void updateIdle(final TaskContext taskContext, final boolean isIdle) {
+        synchronized (RUNNING_TASKS) {
+            Optional<TaskContext> taskContextOptional = findTask(taskContext);
+            if (taskContextOptional.isPresent()) {
+                taskContextOptional.get().setIdle(isIdle);
+            } else {
+                add(taskContext);
+            }
+        }
+    }
+    
+    private Optional<TaskContext> findTask(final TaskContext taskContext) {
+        return getRunningTasks(taskContext.getMetaInfo().getJobName()).stream().filter(each -> each.equals(taskContext)).findFirst();
+    }
+    
+    /**
+     * Remove job from running queue.
+     *
+     * @param jobName job name
+     */
+    public void remove(final String jobName) {
+        RUNNING_TASKS.remove(jobName);
+        if (!isDaemonOrAbsent(jobName)) {
+            return;
+        }
+        regCenter.remove(RunningNode.getRunningJobNodePath(jobName));
+    }
+        
+    /**
+     *  Remove task from running queue.
+     *
+     * @param taskContext task running context
+     */
+    public void remove(final TaskContext taskContext) {
+        getRunningTasks(taskContext.getMetaInfo().getJobName()).remove(taskContext);
+        if (!isDaemonOrAbsent(taskContext.getMetaInfo().getJobName())) {
+            return;
+        }
+        regCenter.remove(RunningNode.getRunningTaskNodePath(taskContext.getMetaInfo().toString()));
+        String jobRootNode = RunningNode.getRunningJobNodePath(taskContext.getMetaInfo().getJobName());
+        if (regCenter.isExisted(jobRootNode) && regCenter.getChildrenKeys(jobRootNode).isEmpty()) {
+            regCenter.remove(jobRootNode);
+        }
+    }
+    
+    private boolean isDaemonOrAbsent(final String jobName) {
+        Optional<CloudJobConfigurationPOJO> cloudJobConfigurationOptional = configurationService.load(jobName);
+        return !cloudJobConfigurationOptional.isPresent() || CloudJobExecutionType.DAEMON == cloudJobConfigurationOptional.get().getJobExecutionType();
+    }
+    
+    /**
+     * Determine whether the job is running or not.
+     *
+     * @param jobName job name
+     * @return true is running, otherwise not
+     */
+    public boolean isJobRunning(final String jobName) {
+        return !getRunningTasks(jobName).isEmpty();
+    }
+    
+    /**
+     * Determine whether the task is running or not.
+     *
+     * @param metaInfo task meta info
+     * @return true is running, otherwise not
+     */
+    public boolean isTaskRunning(final MetaInfo metaInfo) {
+        for (TaskContext each : getRunningTasks(metaInfo.getJobName())) {
+            if (each.getMetaInfo().equals(metaInfo)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Get running tasks by job name.
+     *
+     * @param jobName job name
+     * @return collection of the running tasks
+     */
+    public Collection<TaskContext> getRunningTasks(final String jobName) {
+        Set<TaskContext> taskContexts = new CopyOnWriteArraySet<>();
+        Collection<TaskContext> result = RUNNING_TASKS.putIfAbsent(jobName, taskContexts);
+        return null == result ? taskContexts : result;
+    }
+    
+    /**
+     * Get all running tasks.
+     *
+     * @return collection of all the running tasks
+     */
+    public Map<String, Set<TaskContext>> getAllRunningTasks() {
+        Map<String, Set<TaskContext>> result = new HashMap<>(RUNNING_TASKS.size(), 1);
+        result.putAll(RUNNING_TASKS);
+        return result;
+    }
+    
+    /**
+     * Get all running daemon tasks.
+     *
+     * @return collection of all the running daemon tasks
+     */
+    public Set<TaskContext> getAllRunningDaemonTasks() {
+        List<String> jobKeys = regCenter.getChildrenKeys(RunningNode.ROOT);
+        for (String each : jobKeys) {
+            if (!RUNNING_TASKS.containsKey(each)) {
+                remove(each);
+            }
+        }
+        Set<TaskContext> result = Sets.newHashSet();
+        for (Map.Entry<String, Set<TaskContext>> each : RUNNING_TASKS.entrySet()) {
+            if (isDaemonOrAbsent(each.getKey())) {
+                result.addAll(each.getValue());
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Add mapping of task primary key and hostname.
+     *
+     * @param taskId task primary key
+     * @param hostname host name
+     */
+    public void addMapping(final String taskId, final String hostname) {
+        TASK_HOSTNAME_MAPPER.putIfAbsent(taskId, hostname);
+    }
+    
+    /**
+     * Retrieve the hostname and then remove this task from the mapping.
+     *
+     * @param taskId task primary key
+     * @return the host name of the removed task
+     */
+    public String popMapping(final String taskId) {
+        return TASK_HOSTNAME_MAPPER.remove(taskId);
+    }
+    
+    /**
+     * Clear the running status.
+     */
+    public void clear() {
+        RUNNING_TASKS.clear();
+        TASK_HOSTNAME_MAPPER.clear();
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/StatisticManager.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/StatisticManager.java
new file mode 100644
index 0000000..8b148eb
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/StatisticManager.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.statistics;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobExecutionType;
+import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.StatisticInterval;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobExecutionTypeStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRegisterStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRunningStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskResultStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskRunningStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.ui.repository.StatisticRdbRepository;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.statistics.util.StatisticTimeUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Statistic manager.
+ */
+@Slf4j
+@Service
+public final class StatisticManager {
+    
+    @Autowired
+    private CloudJobConfigurationService configurationService;
+    
+    @Autowired
+    private StatisticRdbRepository rdbRepository;
+    
+    private boolean isRdbConfigured() {
+        return rdbRepository.isEnable();
+    }
+    
+    /**
+     * Get statistic of the recent week.
+     * @return task result statistic
+     */
+    public TaskResultStatistics getTaskResultStatisticsWeekly() {
+        if (!isRdbConfigured()) {
+            return new TaskResultStatistics(0, 0, StatisticInterval.DAY, new Date());
+        }
+        return rdbRepository.getSummedTaskResultStatistics(StatisticTimeUtils.getStatisticTime(StatisticInterval.DAY, -7), StatisticInterval.DAY);
+    }
+    
+    /**
+     * Get statistic since online.
+     * 
+     * @return task result statistic
+     */
+    public TaskResultStatistics getTaskResultStatisticsSinceOnline() {
+        if (!isRdbConfigured()) {
+            return new TaskResultStatistics(0, 0, StatisticInterval.DAY, new Date());
+        }
+        return rdbRepository.getSummedTaskResultStatistics(getOnlineDate(), StatisticInterval.DAY);
+    }
+    
+    /**
+     * Get the latest statistic of the specified interval.
+     * @param statisticInterval statistic interval
+     * @return task result statistic
+     */
+    public TaskResultStatistics findLatestTaskResultStatistics(final StatisticInterval statisticInterval) {
+        if (isRdbConfigured()) {
+            Optional<TaskResultStatistics> result = rdbRepository.findLatestTaskResultStatistics(statisticInterval);
+            if (result.isPresent()) {
+                return result.get();
+            }
+        }
+        return new TaskResultStatistics(0, 0, statisticInterval, new Date());
+    }
+    
+    /**
+     * Get statistic of the recent day.
+     * 
+     * @return task result statistic
+     */
+    public List<TaskResultStatistics> findTaskResultStatisticsDaily() {
+        if (!isRdbConfigured()) {
+            return Collections.emptyList();
+        }
+        return rdbRepository.findTaskResultStatistics(StatisticTimeUtils.getStatisticTime(StatisticInterval.HOUR, -24), StatisticInterval.MINUTE);
+    }
+    
+    /**
+     * Get job execution type statistics.
+     * 
+     * @return Job execution type statistics data object
+     */
+    public JobExecutionTypeStatistics getJobExecutionTypeStatistics() {
+        int transientJobCnt = 0;
+        int daemonJobCnt = 0;
+        for (CloudJobConfigurationPOJO each : configurationService.loadAll()) {
+            if (CloudJobExecutionType.TRANSIENT.equals(each.getJobExecutionType())) {
+                transientJobCnt++;
+            } else if (CloudJobExecutionType.DAEMON.equals(each.getJobExecutionType())) {
+                daemonJobCnt++;
+            }
+        }
+        return new JobExecutionTypeStatistics(transientJobCnt, daemonJobCnt);
+    }
+    
+    /**
+     * Get the collection of task statistics in the most recent week.
+     * 
+     * @return Collection of running task statistics data objects
+     */
+    public List<TaskRunningStatistics> findTaskRunningStatisticsWeekly() {
+        if (!isRdbConfigured()) {
+            return Collections.emptyList();
+        }
+        return rdbRepository.findTaskRunningStatistics(StatisticTimeUtils.getStatisticTime(StatisticInterval.DAY, -7));
+    }
+    
+    /**
+     * Get the collection of job statistics in the most recent week.
+     * 
+     * @return collection of running task statistics data objects
+     */
+    public List<JobRunningStatistics> findJobRunningStatisticsWeekly() {
+        if (!isRdbConfigured()) {
+            return Collections.emptyList();
+        }
+        return rdbRepository.findJobRunningStatistics(StatisticTimeUtils.getStatisticTime(StatisticInterval.DAY, -7));
+    }
+    
+    /**
+     * Get running task statistics data collection since online.
+     * 
+     * @return collection of running task statistics data objects
+     */
+    public List<JobRegisterStatistics> findJobRegisterStatisticsSinceOnline() {
+        if (!isRdbConfigured()) {
+            return Collections.emptyList();
+        }
+        return rdbRepository.findJobRegisterStatistics(getOnlineDate());
+    }
+    
+    private Date getOnlineDate() {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            return formatter.parse("2016-12-16");
+        } catch (final ParseException ex) {
+            return null;
+        }
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/TaskResultMetaData.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/TaskResultMetaData.java
new file mode 100644
index 0000000..e7dde23
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/TaskResultMetaData.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.statistics;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Task result meta data.
+ */
+public final class TaskResultMetaData {
+    
+    private final AtomicInteger successCount;
+    
+    private final AtomicInteger failedCount;
+
+    public TaskResultMetaData() {
+        successCount = new AtomicInteger(0);
+        failedCount = new AtomicInteger(0);
+    }
+    
+    /**
+     * Increase and get success count.
+     * 
+     * @return success count
+     */
+    public int incrementAndGetSuccessCount() {
+        return successCount.incrementAndGet();
+    }
+    
+    /**
+     * Increase and get failed count.
+     * 
+     * @return failed count
+     */
+    public int incrementAndGetFailedCount() {
+        return failedCount.incrementAndGet();
+    }
+    
+    /**
+     * Get success count.
+     * 
+     * @return success count
+     */
+    public int getSuccessCount() {
+        return successCount.get();
+    }
+    
+    /**
+     * Get failed count.
+     * 
+     * @return failed count
+     */
+    public int getFailedCount() {
+        return failedCount.get();
+    }
+    
+    /**
+     * Reset success and failed count.
+     */
+    public void reset() {
+        successCount.set(0);
+        failedCount.set(0);
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/util/StatisticTimeUtils.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/util/StatisticTimeUtils.java
new file mode 100644
index 0000000..4be71ad
--- /dev/null
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/service/statistics/util/StatisticTimeUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.elasticjob.cloud.ui.service.statistics.util;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.elasticjob.cloud.statistics.StatisticInterval;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Statistic time utility.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class StatisticTimeUtils {
+    
+    /**
+     * Get the statistical time with the interval unit.
+     *
+     * @param interval interval
+     * @return Date
+     */
+    public static Date getCurrentStatisticTime(final StatisticInterval interval) {
+        return getStatisticTime(interval, 0);
+    }
+    
+    /**
+     * Get the statistical time with the interval unit.
+     *
+     * @param interval interval
+     * @param offset offset
+     * @return Date
+     */
+    public static Date getStatisticTime(final StatisticInterval interval, final int offset) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.MILLISECOND, 0);
+        calendar.set(Calendar.SECOND, 0);
+        switch (interval) {
+            case DAY:
+                calendar.set(Calendar.MINUTE, 0);
+                calendar.set(Calendar.HOUR_OF_DAY, 0);
+                calendar.add(Calendar.DATE, offset);
+                break;
+            case HOUR:
+                calendar.set(Calendar.MINUTE, 0);
+                calendar.add(Calendar.HOUR_OF_DAY, offset);
+                break;
+            case MINUTE:
+            default:
+                calendar.add(Calendar.MINUTE, offset);
+                break;
+        }
+        return calendar.getTime();
+    }
+}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudAppController.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudAppController.java
index 10562b8..03aec3b 100644
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudAppController.java
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudAppController.java
@@ -17,22 +17,16 @@
 
 package org.apache.shardingsphere.elasticjob.cloud.ui.web.controller;
 
-import com.google.gson.JsonParseException;
-import org.apache.mesos.Protos.ExecutorID;
-import org.apache.mesos.Protos.SlaveID;
 import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.app.CloudAppConfigurationService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.app.pojo.CloudAppConfigurationPOJO;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.job.CloudJobConfigurationService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.exception.AppConfigurationException;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.MesosStateService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.MesosStateService.ExecutorStateInfo;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerManager;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.state.disable.app.DisableAppService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.exception.AppConfigurationException;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.CloudAppConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.app.pojo.CloudAppConfigurationPOJO;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.producer.ProducerManager;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.disable.app.DisableAppService;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.dto.CloudAppConfiguration;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.response.ResponseResult;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.response.ResponseResultUtil;
-import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -66,9 +60,6 @@ public final class CloudAppController {
     @Autowired
     private CloudJobConfigurationService jobConfigService;
     
-    @Autowired
-    private MesosStateService mesosStateService;
-    
     /**
      * Register app config.
      * @param appConfig cloud app config
@@ -131,11 +122,6 @@ public final class CloudAppController {
     public ResponseResult disable(@PathVariable("appName") final String appName) {
         if (appConfigService.load(appName).isPresent()) {
             disableAppService.add(appName);
-            for (CloudJobConfigurationPOJO each : jobConfigService.loadAll()) {
-                if (appName.equals(each.getAppName())) {
-                    producerManager.unschedule(each.getJobName());
-                }
-            }
         }
         return ResponseResultUtil.success();
     }
@@ -148,11 +134,6 @@ public final class CloudAppController {
     public ResponseResult enable(@PathVariable("appName") final String appName) {
         if (appConfigService.load(appName).isPresent()) {
             disableAppService.remove(appName);
-            for (CloudJobConfigurationPOJO each : jobConfigService.loadAll()) {
-                if (appName.equals(each.getAppName())) {
-                    producerManager.reschedule(each.getJobName());
-                }
-            }
         }
         return ResponseResultUtil.success();
     }
@@ -165,7 +146,6 @@ public final class CloudAppController {
     public ResponseResult deregister(@PathVariable("appName") final String appName) {
         if (appConfigService.load(appName).isPresent()) {
             removeAppAndJobConfigurations(appName);
-            stopExecutors(appName);
         }
         return ResponseResultUtil.success();
     }
@@ -180,27 +160,14 @@ public final class CloudAppController {
         appConfigService.remove(appName);
     }
     
-    private void stopExecutors(final String appName) {
-        try {
-            Collection<ExecutorStateInfo> executorBriefInfo = mesosStateService.executors(appName);
-            for (ExecutorStateInfo each : executorBriefInfo) {
-                producerManager.sendFrameworkMessage(ExecutorID.newBuilder().setValue(each.getId()).build(),
-                                                     SlaveID.newBuilder().setValue(each.getSlaveId()).build(),
-                                                     "STOP".getBytes());
-            }
-        } catch (final JsonParseException ex) {
-            throw new JobSystemException(ex);
-        }
-    }
-    
     private Collection<CloudAppConfiguration> build(final Collection<CloudAppConfigurationPOJO> cloudAppConfigurationPOJOS) {
-        return cloudAppConfigurationPOJOS.stream().map(this::convert).collect(Collectors.toList());
+        return cloudAppConfigurationPOJOS.stream().map(each -> convert(each)).collect(Collectors.toList());
     }
     
     private CloudAppConfiguration convert(final CloudAppConfigurationPOJO cloudAppConfigurationPOJO) {
-        CloudAppConfiguration result = new CloudAppConfiguration();
-        BeanUtils.copyProperties(cloudAppConfigurationPOJO, result);
-        result.setDisabled(disableAppService.isDisabled(cloudAppConfigurationPOJO.getAppName()));
-        return result;
+        CloudAppConfiguration cloudAppConfiguration = new CloudAppConfiguration();
+        BeanUtils.copyProperties(cloudAppConfigurationPOJO, cloudAppConfiguration);
+        cloudAppConfiguration.setDisabled(disableAppService.isDisabled(cloudAppConfigurationPOJO.getAppName()));
+        return cloudAppConfiguration;
     }
 }
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudJobController.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudJobController.java
index 0170fdd..db8c440 100644
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudJobController.java
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudJobController.java
@@ -21,17 +21,17 @@ import com.google.common.base.Strings;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.elasticjob.cloud.config.CloudJobExecutionType;
 import org.apache.shardingsphere.elasticjob.cloud.config.pojo.CloudJobConfigurationPOJO;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.config.job.CloudJobConfigurationService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.FacadeService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerManager;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.state.failover.FailoverTaskInfo;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.statistics.StatisticManager;
 import org.apache.shardingsphere.elasticjob.cloud.statistics.StatisticInterval;
 import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobExecutionTypeStatistics;
 import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRegisterStatistics;
 import org.apache.shardingsphere.elasticjob.cloud.statistics.type.job.JobRunningStatistics;
 import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskResultStatistics;
 import org.apache.shardingsphere.elasticjob.cloud.statistics.type.task.TaskRunningStatistics;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.FacadeService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.job.CloudJobConfigurationService;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.producer.ProducerManager;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.state.failover.FailoverTaskInfo;
+import org.apache.shardingsphere.elasticjob.cloud.ui.service.statistics.StatisticManager;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.controller.search.JobEventRdbSearch;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.response.ResponseResult;
 import org.apache.shardingsphere.elasticjob.cloud.ui.web.response.ResponseResultUtil;
@@ -138,7 +138,6 @@ public final class CloudJobController {
         Optional<CloudJobConfigurationPOJO> configOptional = jobConfigService.load(jobName);
         if (configOptional.isPresent()) {
             facadeService.enableJob(jobName);
-            producerManager.reschedule(jobName);
         }
         return ResponseResultUtil.build(Boolean.TRUE);
     }
@@ -151,7 +150,6 @@ public final class CloudJobController {
     public ResponseResult<Boolean> disable(@PathVariable("jobName") final String jobName) {
         if (jobConfigService.load(jobName).isPresent()) {
             facadeService.disableJob(jobName);
-            producerManager.unschedule(jobName);
         }
         return ResponseResultUtil.build(Boolean.TRUE);
     }
@@ -242,7 +240,7 @@ public final class CloudJobController {
     @PostMapping("/events/executions")
     public ResponseResult<JobEventRdbSearch.Result<JobExecutionEvent>> findJobExecutionEvents(@RequestParam final MultiValueMap<String, String> requestParams) throws ParseException {
         if (!isRdbConfigured()) {
-            return ResponseResultUtil.build(new JobEventRdbSearch.Result<>(0, Collections.emptyList()));
+            return ResponseResultUtil.build(new JobEventRdbSearch.Result<>(0, Collections.<JobExecutionEvent>emptyList()));
         }
         return ResponseResultUtil.build(jobEventRdbSearch.findJobExecutionEvents(buildCondition(requestParams, new String[]{"jobName", "taskId", "ip", "isSuccess"})));
     }
@@ -256,7 +254,7 @@ public final class CloudJobController {
     @PostMapping("/events/statusTraces")
     public ResponseResult<JobEventRdbSearch.Result<JobStatusTraceEvent>> findJobStatusTraceEvents(@RequestParam final MultiValueMap<String, String> requestParams) throws ParseException {
         if (!isRdbConfigured()) {
-            return ResponseResultUtil.build(new JobEventRdbSearch.Result<>(0, Collections.emptyList()));
+            return ResponseResultUtil.build(new JobEventRdbSearch.Result<>(0, Collections.<JobStatusTraceEvent>emptyList()));
         }
         return ResponseResultUtil.build(jobEventRdbSearch.findJobStatusTraceEvents(buildCondition(requestParams, new String[]{"jobName", "taskId", "slaveId", "source", "executionType", "state"})));
     }
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudOperationController.java b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudOperationController.java
deleted file mode 100644
index c55808d..0000000
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/cloud/ui/web/controller/CloudOperationController.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.elasticjob.cloud.ui.web.controller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.gson.JsonParseException;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.MesosStateService;
-import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.ReconcileService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.apache.shardingsphere.elasticjob.infra.exception.JobSystemException;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Cloud operation restful api.
- */
-@Slf4j
-@RestController
-@RequestMapping("/api/operate")
-public final class CloudOperationController {
-    
-    private static final long RECONCILE_MILLIS_INTERVAL = 10 * 1000L;
-    
-    private static long lastReconcileTime;
-    
-    @Autowired
-    private ReconcileService reconcileService;
-    
-    @Autowired
-    private MesosStateService mesosStateService;
-    
-    /**
-     * Explicit reconcile service.
-     */
-    @PostMapping("/reconcile/explicit")
-    public void explicitReconcile() {
-        validReconcileInterval();
-        reconcileService.explicitReconcile();
-    }
-    
-    /**
-     * Implicit reconcile service.
-     */
-    @PostMapping("/reconcile/implicit")
-    public void implicitReconcile() {
-        validReconcileInterval();
-        reconcileService.implicitReconcile();
-    }
-    
-    private void validReconcileInterval() {
-        if (System.currentTimeMillis() < lastReconcileTime + RECONCILE_MILLIS_INTERVAL) {
-            throw new RuntimeException("Repeat explicitReconcile");
-        }
-        lastReconcileTime = System.currentTimeMillis();
-    }
-    
-    /**
-     * Get sandbox of the cloud job by app name.
-     * @param appName application name
-     * @return sandbox info
-     */
-    @GetMapping("/sandbox")
-    public Collection<Map<String, String>> sandbox(@RequestParam("appName") final String appName) {
-        Preconditions.checkArgument(!Strings.isNullOrEmpty(appName), "Lack param 'appName'");
-        try {
-            return mesosStateService.sandbox(appName);
-        } catch (final JsonParseException ex) {
-            throw new JobSystemException(ex);
-        }
-    }
-}
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/application.properties b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/application.properties
index f31d024..c5b6436 100644
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/application.properties
+++ b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/application.properties
@@ -21,3 +21,25 @@ auth.root_username=root
 auth.root_password=root
 auth.guest_username=guest
 auth.guest_password=guest
+
+# ElasticJob-Cloud's zookeeper address
+zk.servers=127.0.0.1:2181
+
+# ElasticJob-Cloud's zookeeper namespace
+zk.namespace=elasticjob-cloud
+
+# ElasticJob-Cloud's zookeeper digest
+zk.digest=
+
+# Max size of job accumulated
+job.state.queue_size=10000
+
+# Event trace rdb config
+
+#event.trace.rdb_driver=com.mysql.jdbc.Driver
+
+#event.trace.rdb_url=jdbc:mysql://localhost:3306/elastic_job_cloud_log
+
+#event.trace.rdb_username=root
+
+#event.trace.rdb_password=
\ No newline at end of file
diff --git a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/conf/elasticjob-cloud-scheduler.properties b/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/conf/elasticjob-cloud-scheduler.properties
deleted file mode 100644
index 7e17d93..0000000
--- a/shardingsphere-elasticjob-cloud-ui/shardingsphere-elasticjob-cloud-ui-backend/src/main/resources/conf/elasticjob-cloud-scheduler.properties
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Routable IP address
-hostname=127.0.0.1
-
-# Username for mesos framework
-user=
-
-# Mesos zookeeper address
-mesos_url=zk://127.0.0.1:2181/mesos
-
-# Role for mesos framework
-
-#mesos_role=
-
-# ElasticJob-Cloud's zookeeper address
-zk_servers=127.0.0.1:2181
-
-# ElasticJob-Cloud's zookeeper namespace
-zk_namespace=elasticjob-cloud
-
-# ElasticJob-Cloud's zookeeper digest
-zk_digest=
-
-# Job rest API port
-http_port=8899
-        
-# Max size of job accumulated
-job_state_queue_size=10000
-
-# Event trace rdb config
-
-#event_trace_rdb_driver=com.mysql.jdbc.Driver
-
-#event_trace_rdb_url=jdbc:mysql://localhost:3306/elastic_job_cloud_log
-
-#event_trace_rdb_username=root
-
-#event_trace_rdb_password=
-
-# Task reconciliation interval
-
-#reconcile_interval_minutes=-1
-
-# Enable/Disable mesos partition aware feature
-
-# enable_partition_aware=false
diff --git a/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/application.properties b/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/application.properties
index ceff8ca..c5b6436 100644
--- a/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/application.properties
+++ b/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/application.properties
@@ -22,4 +22,24 @@ auth.root_password=root
 auth.guest_username=guest
 auth.guest_password=guest
 
+# ElasticJob-Cloud's zookeeper address
+zk.servers=127.0.0.1:2181
 
+# ElasticJob-Cloud's zookeeper namespace
+zk.namespace=elasticjob-cloud
+
+# ElasticJob-Cloud's zookeeper digest
+zk.digest=
+
+# Max size of job accumulated
+job.state.queue_size=10000
+
+# Event trace rdb config
+
+#event.trace.rdb_driver=com.mysql.jdbc.Driver
+
+#event.trace.rdb_url=jdbc:mysql://localhost:3306/elastic_job_cloud_log
+
+#event.trace.rdb_username=root
+
+#event.trace.rdb_password=
\ No newline at end of file
diff --git a/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/elasticjob-cloud-scheduler.properties b/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/elasticjob-cloud-scheduler.properties
deleted file mode 100644
index 7e17d93..0000000
--- a/shardingsphere-elasticjob-ui-distribution/shardingsphere-elasticjob-cloud-ui-bin-distribution/src/main/resources/elasticjob-cloud-scheduler.properties
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Routable IP address
-hostname=127.0.0.1
-
-# Username for mesos framework
-user=
-
-# Mesos zookeeper address
-mesos_url=zk://127.0.0.1:2181/mesos
-
-# Role for mesos framework
-
-#mesos_role=
-
-# ElasticJob-Cloud's zookeeper address
-zk_servers=127.0.0.1:2181
-
-# ElasticJob-Cloud's zookeeper namespace
-zk_namespace=elasticjob-cloud
-
-# ElasticJob-Cloud's zookeeper digest
-zk_digest=
-
-# Job rest API port
-http_port=8899
-        
-# Max size of job accumulated
-job_state_queue_size=10000
-
-# Event trace rdb config
-
-#event_trace_rdb_driver=com.mysql.jdbc.Driver
-
-#event_trace_rdb_url=jdbc:mysql://localhost:3306/elastic_job_cloud_log
-
-#event_trace_rdb_username=root
-
-#event_trace_rdb_password=
-
-# Task reconciliation interval
-
-#reconcile_interval_minutes=-1
-
-# Enable/Disable mesos partition aware feature
-
-# enable_partition_aware=false