From 4230d5a737b7889254806969ae153817fd19d181 Mon Sep 17 00:00:00 2001 From: dailidong Date: Thu, 5 Mar 2020 17:32:40 +0800 Subject: [PATCH] add embedded database h2 and update embedded zookeeper (#2082) add embedded database h2 and update embedded zookeeper --- dolphinscheduler-dao/pom.xml | 19 +++- .../src/main/resources/application.properties | 4 + .../server/zk/StandaloneZKServerForTest.java | 100 ------------------ dolphinscheduler-service/pom.xml | 5 + .../service/zk}/ZKServer.java | 87 ++++++++------- .../src/main/resources/quartz.properties | 4 + .../service/zk/ZKServerTest.java | 41 +++++++ .../test/java/queue/BaseTaskQueueTest.java | 1 + pom.xml | 14 ++- sql/h2.mv.db | Bin 0 -> 110592 bytes 10 files changed, 121 insertions(+), 154 deletions(-) delete mode 100644 dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/zk/StandaloneZKServerForTest.java rename dolphinscheduler-service/src/{test/java/queue => main/java/org/apache/dolphinscheduler/service/zk}/ZKServer.java (67%) create mode 100644 dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/zk/ZKServerTest.java create mode 100644 sql/h2.mv.db diff --git a/dolphinscheduler-dao/pom.xml b/dolphinscheduler-dao/pom.xml index 20d19410e2..fd43458f87 100644 --- a/dolphinscheduler-dao/pom.xml +++ b/dolphinscheduler-dao/pom.xml @@ -44,6 +44,12 @@ com.baomidou mybatis-plus-boot-starter ${mybatis-plus.version} + + + org.apache.logging.log4j + log4j-to-slf4j + + org.postgresql @@ -71,6 +77,14 @@ log4j-api org.apache.logging.log4j + + org.springframework.boot + spring-boot-starter-tomcat + + + org.apache.logging.log4j + log4j-to-slf4j + @@ -78,7 +92,10 @@ mysql mysql-connector-java - + + com.h2database + h2 + com.alibaba druid diff --git a/dolphinscheduler-dao/src/main/resources/application.properties b/dolphinscheduler-dao/src/main/resources/application.properties index 34bb9f916b..06b0ee94d5 100644 --- a/dolphinscheduler-dao/src/main/resources/application.properties +++ b/dolphinscheduler-dao/src/main/resources/application.properties @@ -23,6 +23,10 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/dolphinscheduler # mysql #spring.datasource.driver-class-name=com.mysql.jdbc.Driver #spring.datasource.url=jdbc:mysql://192.168.xx.xx:3306/dolphinscheduler?useUnicode=true&characterEncoding=UTF-8 +# h2 +#spring.datasource.driver-class-name=org.h2.Driver +#spring.datasource.url=jdbc:h2:file:../sql/h2;AUTO_SERVER=TRUE + spring.datasource.username=test spring.datasource.password=test diff --git a/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/zk/StandaloneZKServerForTest.java b/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/zk/StandaloneZKServerForTest.java deleted file mode 100644 index 679862f102..0000000000 --- a/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/zk/StandaloneZKServerForTest.java +++ /dev/null @@ -1,100 +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.dolphinscheduler.server.zk; - -import org.apache.dolphinscheduler.common.thread.ThreadPoolExecutors; -import org.apache.zookeeper.server.ServerConfig; -import org.apache.zookeeper.server.ZooKeeperServerMain; -import org.apache.zookeeper.server.quorum.QuorumPeerConfig; -import org.junit.Before; -import org.junit.Ignore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.Properties; - - -/** - * just for test - */ -@Ignore -public class StandaloneZKServerForTest { - - private static final Logger logger = LoggerFactory.getLogger(StandaloneZKServerForTest.class); - - private static volatile ZooKeeperServerMain zkServer = null; - - - @Before - public void before() { - logger.info("standalone zookeeper server for test service start "); - - ThreadPoolExecutors.getInstance().execute(new Runnable() { - @Override - public void run() { - - //delete zk data dir ? - File zkFile = new File(System.getProperty("java.io.tmpdir"), "zookeeper"); - - startStandaloneServer("2000", zkFile.getAbsolutePath(), "2181", "10", "5"); - } - }); - - } - - - /** - * start zk server - * @param tickTime zookeeper ticktime - * @param dataDir zookeeper data dir - * @param clientPort zookeeper client port - * @param initLimit zookeeper init limit - * @param syncLimit zookeeper sync limit - */ - private void startStandaloneServer(String tickTime, String dataDir, String clientPort, String initLimit, String syncLimit) { - Properties props = new Properties(); - props.setProperty("tickTime", tickTime); - props.setProperty("dataDir", dataDir); - props.setProperty("clientPort", clientPort); - props.setProperty("initLimit", initLimit); - props.setProperty("syncLimit", syncLimit); - - QuorumPeerConfig quorumConfig = new QuorumPeerConfig(); - try { - quorumConfig.parseProperties(props); - - if(zkServer == null ){ - - synchronized (StandaloneZKServerForTest.class){ - if(zkServer == null ){ - zkServer = new ZooKeeperServerMain(); - final ServerConfig config = new ServerConfig(); - config.readFrom(quorumConfig); - zkServer.runFromConfig(config); - } - } - - } - - } catch (Exception e) { - logger.error("start standalone server fail!", e); - } - } - - -} \ No newline at end of file diff --git a/dolphinscheduler-service/pom.xml b/dolphinscheduler-service/pom.xml index 7d775d5497..03bb94dc29 100644 --- a/dolphinscheduler-service/pom.xml +++ b/dolphinscheduler-service/pom.xml @@ -48,6 +48,11 @@ + + org.apache.logging.log4j + log4j-core + + org.quartz-scheduler quartz-jobs diff --git a/dolphinscheduler-service/src/test/java/queue/ZKServer.java b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/zk/ZKServer.java similarity index 67% rename from dolphinscheduler-service/src/test/java/queue/ZKServer.java rename to dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/zk/ZKServer.java index 3d503d5691..96331405d4 100644 --- a/dolphinscheduler-service/src/test/java/queue/ZKServer.java +++ b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/zk/ZKServer.java @@ -14,11 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package queue; +package org.apache.dolphinscheduler.service.zk; -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.CuratorFrameworkFactory; -import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.zookeeper.server.ZooKeeperServer; import org.apache.zookeeper.server.ZooKeeperServerMain; import org.apache.zookeeper.server.quorum.QuorumPeerConfig; import org.slf4j.Logger; @@ -26,27 +24,45 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** - * just for test + * just speed experience version + * embedded zookeeper service */ public class ZKServer { - private static final Logger logger = LoggerFactory.getLogger(ZKServer.class); private static volatile PublicZooKeeperServerMain zkServer = null; public static final int DEFAULT_ZK_TEST_PORT = 2181; - public static final String DEFAULT_ZK_STR = "localhost:" + DEFAULT_ZK_TEST_PORT; - private static String dataDir = null; private static final AtomicBoolean isStarted = new AtomicBoolean(false); + public static void main(String[] args) { + if(!isStarted()){ + ZKServer.start(); + + /** + * register hooks, which are called before the process exits + */ + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + stop(); + } + })); + }else{ + logger.info("zk server aleady started"); + } + } + + /** + * start service + */ public static void start() { try { startLocalZkServer(DEFAULT_ZK_TEST_PORT); @@ -79,7 +95,8 @@ public class ZKServer { * @param port The port to listen on */ public static void startLocalZkServer(final int port) { - startLocalZkServer(port, org.apache.commons.io.FileUtils.getTempDirectoryPath() + File.separator + "test-" + System.currentTimeMillis()); + + startLocalZkServer(port, System.getProperty("user.dir") +"/zookeeper_data", ZooKeeperServer.DEFAULT_TICK_TIME,"20"); } /** @@ -87,48 +104,28 @@ public class ZKServer { * * @param port The port to listen on * @param dataDirPath The path for the Zk data directory + * @param tickTime zk tick time + * @param maxClientCnxns zk max client connections */ - private static synchronized void startLocalZkServer(final int port, final String dataDirPath) { + private static synchronized void startLocalZkServer(final int port, final String dataDirPath,final int tickTime,String maxClientCnxns) { if (zkServer != null) { throw new RuntimeException("Zookeeper server is already started!"); } - try { - zkServer = new PublicZooKeeperServerMain(); - logger.info("Zookeeper data path : {} ", dataDirPath); - dataDir = dataDirPath; - final String[] args = new String[]{Integer.toString(port), dataDirPath}; - Thread init = new Thread(new Runnable() { - @Override - public void run() { - try { - zkServer.initializeAndRun(args); - } catch (QuorumPeerConfig.ConfigException e) { - logger.warn("Caught exception while starting ZK", e); - } catch (IOException e) { - logger.warn("Caught exception while starting ZK", e); - } - } - }, "init-zk-thread"); - init.start(); - } catch (Exception e) { - logger.warn("Caught exception while starting ZK", e); - throw new RuntimeException(e); - } - - CuratorFramework zkClient = CuratorFrameworkFactory.builder() - .connectString(DEFAULT_ZK_STR) - .retryPolicy(new ExponentialBackoffRetry(10,100)) - .sessionTimeoutMs(1000 * 30) - .connectionTimeoutMs(1000 * 30) - .build(); + zkServer = new PublicZooKeeperServerMain(); + logger.info("Zookeeper data path : {} ", dataDirPath); + dataDir = dataDirPath; + final String[] args = new String[]{Integer.toString(port), dataDirPath, Integer.toString(tickTime), maxClientCnxns}; try { - zkClient.blockUntilConnected(10, TimeUnit.SECONDS); - zkClient.close(); - } catch (InterruptedException ignore) { + logger.info("Zookeeper server started "); + isStarted.compareAndSet(false, true); + + zkServer.initializeAndRun(args); + } catch (QuorumPeerConfig.ConfigException e) { + logger.warn("Caught exception while starting ZK", e); + } catch (IOException e) { + logger.warn("Caught exception while starting ZK", e); } - isStarted.compareAndSet(false, true); - logger.info("zk server started"); } /** diff --git a/dolphinscheduler-service/src/main/resources/quartz.properties b/dolphinscheduler-service/src/main/resources/quartz.properties index 9c8930b647..b01be394c6 100644 --- a/dolphinscheduler-service/src/main/resources/quartz.properties +++ b/dolphinscheduler-service/src/main/resources/quartz.properties @@ -26,6 +26,10 @@ org.quartz.dataSource.myDs.URL = jdbc:postgresql://localhost:5432/dolphinschedul # mysql #org.quartz.dataSource.myDs.driver = com.mysql.jdbc.Driver #org.quartz.dataSource.myDs.URL = jdbc:mysql://localhost:3306/dolphinscheduler?characterEncoding=utf8 +#h2 +#org.quartz.dataSource.myDs.driver=org.h2.Driver +#org.quartz.dataSource.myDs.URL=jdbc:h2:file:/Users/stone/work/myworkspace/incubator-dolphinscheduler/h2;AUTO_SERVER=TRUE + org.quartz.dataSource.myDs.user = test org.quartz.dataSource.myDs.password = test diff --git a/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/zk/ZKServerTest.java b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/zk/ZKServerTest.java new file mode 100644 index 0000000000..48cde32287 --- /dev/null +++ b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/zk/ZKServerTest.java @@ -0,0 +1,41 @@ +/* + * 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.dolphinscheduler.service.zk; + +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.*; + +@Ignore +public class ZKServerTest { + + @Test + public void start() { + //ZKServer is a process, can't unit test + } + + @Test + public void isStarted() { + + } + + @Test + public void stop() { + ZKServer.stop(); + } +} \ No newline at end of file diff --git a/dolphinscheduler-service/src/test/java/queue/BaseTaskQueueTest.java b/dolphinscheduler-service/src/test/java/queue/BaseTaskQueueTest.java index a0cc457e22..97ab9969a3 100644 --- a/dolphinscheduler-service/src/test/java/queue/BaseTaskQueueTest.java +++ b/dolphinscheduler-service/src/test/java/queue/BaseTaskQueueTest.java @@ -18,6 +18,7 @@ package queue; import org.apache.dolphinscheduler.service.queue.ITaskQueue; import org.apache.dolphinscheduler.service.queue.TaskQueueFactory; +import org.apache.dolphinscheduler.service.zk.ZKServer; import org.junit.*; /** diff --git a/pom.xml b/pom.xml index 8a1e9b98f2..57063a86c2 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 5.0.5 1.2.61 1.1.14 - 1.3.163 + 1.4.200 1.6 1.1.1 4.4.1 @@ -200,13 +200,6 @@ ${spring.version} test - - com.h2database - h2 - ${h2.version} - test - - org.apache.dolphinscheduler dolphinscheduler-server @@ -349,6 +342,11 @@ ${mysql.connector.version} test + + com.h2database + h2 + ${h2.version} + org.slf4j slf4j-api diff --git a/sql/h2.mv.db b/sql/h2.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..42ea540bd37b54496241f1669d3455f3b9806cf4 GIT binary patch literal 110592 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

9+dVANTZwqCRi-f@HUQ_ zNG$Ceo}8V)wdCShD<3f;4!|VNq79D54(pV4FX4zBUo?uj8-cl#u`%aA<~+EKJB8j& zfZpe#py%geECl+GM)&aCgZ~hDh(sVgLcI?N{Cpe)(&PIj51ivcJ+uVC;+Kj)MsI1~ z6izsqW`}gfl#lXwsd_t3OT_67>3}*FGFvI!wgGPMi4QmbH9HJ%z838iZT;=grsf|H zYyL}kJPbZtu+iIkwgYW1wmE~=k;Tg7)awawxTBQbvN%=6wKT0*%j$;gPo0RkZ!%s) zbV894p+KFY-JaR`73H|Uj!jPBL~}u>GA3|CkU$9;DGfVGCT7P=mGbZw-Rw(Qyh@J! d@3Ft#wPUc#9S1<(Y#KSEIj7jaXZvyC{|~3$rtbg% literal 0 HcmV?d00001