mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
finished dbLockService & Server elect
This commit is contained in:
parent
03f167cb44
commit
c064602648
@ -17,4 +17,5 @@ import java.io.Serializable;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class AskResponse implements Serializable {
|
public class AskResponse implements Serializable {
|
||||||
private boolean success;
|
private boolean success;
|
||||||
|
private Object extra;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
<hikaricp.version>3.4.2</hikaricp.version>
|
<hikaricp.version>3.4.2</hikaricp.version>
|
||||||
<mysql.version>8.0.19</mysql.version>
|
<mysql.version>8.0.19</mysql.version>
|
||||||
<commons.lang.version>3.10</commons.lang.version>
|
<commons.lang.version>3.10</commons.lang.version>
|
||||||
|
<curator.version>4.3.0</curator.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -53,6 +54,14 @@
|
|||||||
<version>${akka.version}</version>
|
<version>${akka.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- curator -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.curator</groupId>
|
||||||
|
<artifactId>curator-recipes</artifactId>
|
||||||
|
<version>${curator.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.github.kfcfans.oms.server.common.config;
|
||||||
|
|
||||||
|
import org.apache.curator.framework.CuratorFramework;
|
||||||
|
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||||
|
import org.apache.curator.retry.ExponentialBackoffRetry;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZooKeeper 连接配置
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2020/4/4
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CuratorConfig {
|
||||||
|
|
||||||
|
@Value("${zookeeper.address}")
|
||||||
|
private String zkAddress;
|
||||||
|
|
||||||
|
@Bean("omsCurator")
|
||||||
|
public CuratorFramework initCurator() {
|
||||||
|
CuratorFramework client = CuratorFrameworkFactory.builder()
|
||||||
|
.namespace("oms")
|
||||||
|
// zookeeper 地址,多值用 , 分割即可
|
||||||
|
.connectString(zkAddress)
|
||||||
|
.sessionTimeoutMs(1000)
|
||||||
|
.connectionTimeoutMs(1000)
|
||||||
|
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
|
||||||
|
.build();
|
||||||
|
client.start();
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.github.kfcfans.oms.server.core.actors;
|
package com.github.kfcfans.oms.server.core.akka;
|
||||||
|
|
||||||
|
import akka.actor.ActorPath;
|
||||||
|
import akka.actor.ActorSelection;
|
||||||
import akka.actor.ActorSystem;
|
import akka.actor.ActorSystem;
|
||||||
import akka.actor.Props;
|
import akka.actor.Props;
|
||||||
import com.github.kfcfans.common.RemoteConstant;
|
import com.github.kfcfans.common.RemoteConstant;
|
||||||
@ -7,6 +9,7 @@ import com.github.kfcfans.common.utils.NetUtils;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.typesafe.config.Config;
|
import com.typesafe.config.Config;
|
||||||
import com.typesafe.config.ConfigFactory;
|
import com.typesafe.config.ConfigFactory;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -21,6 +24,7 @@ import java.util.Map;
|
|||||||
public class OhMyServer {
|
public class OhMyServer {
|
||||||
|
|
||||||
public static ActorSystem actorSystem;
|
public static ActorSystem actorSystem;
|
||||||
|
@Getter
|
||||||
private static String actorSystemAddress;
|
private static String actorSystemAddress;
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
@ -41,4 +45,14 @@ public class OhMyServer {
|
|||||||
actorSystem.actorOf(Props.create(ServerActor.class), RemoteConstant.SERVER_ACTOR_NAME);
|
actorSystem.actorOf(Props.create(ServerActor.class), RemoteConstant.SERVER_ACTOR_NAME);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 ServerActor 的 ActorSelection
|
||||||
|
* @param address IP:port
|
||||||
|
* @return ActorSelection
|
||||||
|
*/
|
||||||
|
public static ActorSelection getServerActor(String address) {
|
||||||
|
String path = String.format("akka://%s@%s/user/%s", RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, address, RemoteConstant.SERVER_ACTOR_NAME);
|
||||||
|
return actorSystem.actorSelection(path);
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.github.kfcfans.oms.server.core.akka;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测目标机器是否存活
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2020/4/5
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Ping implements Serializable {
|
||||||
|
private long currentTime;
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
package com.github.kfcfans.oms.server.core.actors;
|
package com.github.kfcfans.oms.server.core.akka;
|
||||||
|
|
||||||
import akka.actor.AbstractActor;
|
import akka.actor.AbstractActor;
|
||||||
import com.github.kfcfans.common.request.WorkerHeartbeat;
|
import com.github.kfcfans.common.request.WorkerHeartbeat;
|
||||||
|
import com.github.kfcfans.common.response.AskResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,13 +18,22 @@ public class ServerActor extends AbstractActor {
|
|||||||
public Receive createReceive() {
|
public Receive createReceive() {
|
||||||
return receiveBuilder()
|
return receiveBuilder()
|
||||||
.match(WorkerHeartbeat.class, this::onReceiveWorkerHeartbeat)
|
.match(WorkerHeartbeat.class, this::onReceiveWorkerHeartbeat)
|
||||||
|
.match(Ping.class, this::onReceivePing)
|
||||||
.matchAny(obj -> log.warn("[ServerActor] receive unknown request: {}.", obj))
|
.matchAny(obj -> log.warn("[ServerActor] receive unknown request: {}.", obj))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理存活检测的请求
|
||||||
|
* @param ping 存活检测请求
|
||||||
|
*/
|
||||||
|
private void onReceivePing(Ping ping) {
|
||||||
|
AskResponse askResponse = new AskResponse();
|
||||||
|
askResponse.setSuccess(true);
|
||||||
|
askResponse.setExtra(System.currentTimeMillis() - ping.getCurrentTime());
|
||||||
|
getSender().tell(askResponse, getSelf());
|
||||||
|
}
|
||||||
|
|
||||||
private void onReceiveWorkerHeartbeat(WorkerHeartbeat heartbeat) {
|
private void onReceiveWorkerHeartbeat(WorkerHeartbeat heartbeat) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -23,6 +23,8 @@ public class AppInfoDO {
|
|||||||
private String appName;
|
private String appName;
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
private String currentServer;
|
||||||
|
|
||||||
private Date gmtCreate;
|
private Date gmtCreate;
|
||||||
private Date gmtModified;
|
private Date gmtModified;
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,14 @@ public class OmsLockDO {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String lockName;
|
private String lockName;
|
||||||
private String owner;
|
private String ownerIP;
|
||||||
|
|
||||||
private Date gmtCreate;
|
private Date gmtCreate;
|
||||||
private Date gmtModified;
|
private Date gmtModified;
|
||||||
|
|
||||||
public OmsLockDO(String lockName, String owner) {
|
public OmsLockDO(String lockName, String ownerIP) {
|
||||||
this.lockName = lockName;
|
this.lockName = lockName;
|
||||||
this.owner = owner;
|
this.ownerIP = ownerIP;
|
||||||
this.gmtCreate = new Date();
|
this.gmtCreate = new Date();
|
||||||
this.gmtModified = this.gmtCreate;
|
this.gmtModified = this.gmtCreate;
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
* @since 2020/4/1
|
* @since 2020/4/1
|
||||||
*/
|
*/
|
||||||
public interface AppInfoRepository extends JpaRepository<AppInfoDO, Long> {
|
public interface AppInfoRepository extends JpaRepository<AppInfoDO, Long> {
|
||||||
|
|
||||||
|
AppInfoDO findByAppName(String appName);
|
||||||
}
|
}
|
||||||
|
@ -19,4 +19,6 @@ public interface OmsLockRepository extends JpaRepository<OmsLockDO, Long> {
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Query(value = "delete from oms_lock where lock_name = ?1", nativeQuery = true)
|
@Query(value = "delete from oms_lock where lock_name = ?1", nativeQuery = true)
|
||||||
int deleteByLockName(String lockName);
|
int deleteByLockName(String lockName);
|
||||||
|
|
||||||
|
OmsLockDO findByLockName(String lockName);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
package com.github.kfcfans.oms.server.service.ha;
|
||||||
|
|
||||||
|
import akka.actor.ActorSelection;
|
||||||
|
import akka.pattern.Patterns;
|
||||||
|
import com.github.kfcfans.common.response.AskResponse;
|
||||||
|
import com.github.kfcfans.oms.server.core.akka.OhMyServer;
|
||||||
|
import com.github.kfcfans.oms.server.core.akka.Ping;
|
||||||
|
import com.github.kfcfans.oms.server.persistence.model.AppInfoDO;
|
||||||
|
import com.github.kfcfans.oms.server.persistence.repository.AppInfoRepository;
|
||||||
|
import com.github.kfcfans.oms.server.service.lock.LockService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.CompletionStage;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Worker请求分配Server服务
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2020/4/5
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ServerSelectService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LockService lockService;
|
||||||
|
@Resource
|
||||||
|
private AppInfoRepository appInfoRepository;
|
||||||
|
|
||||||
|
private static final int RETRY_TIMES = 10;
|
||||||
|
private static final long PING_TIMEOUT_MS = 5000;
|
||||||
|
private static final long WAIT_LOCK_TIME = 1000;
|
||||||
|
private static final String SERVER_ELECT_LOCK = "server_elect_%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取某个应用对应的Server
|
||||||
|
* 缺点:如果server死而复生,可能造成worker集群脑裂,不过感觉影响不是很大 & 概率极低,就不管了
|
||||||
|
* @param appName 应用名称
|
||||||
|
* @return 当前可用的Server
|
||||||
|
*/
|
||||||
|
public String getServer(String appName) {
|
||||||
|
|
||||||
|
for (int i = 0; i < RETRY_TIMES; i++) {
|
||||||
|
|
||||||
|
// 无锁获取当前数据库中的Server
|
||||||
|
AppInfoDO app = appInfoRepository.findByAppName(appName);
|
||||||
|
if (app == null) {
|
||||||
|
throw new RuntimeException(appName + " is not registered!");
|
||||||
|
}
|
||||||
|
String originServer = app.getCurrentServer();
|
||||||
|
if (isActive(originServer)) {
|
||||||
|
return originServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取失败,重新进行Server选举,需要加锁
|
||||||
|
String lockName = String.format(SERVER_ELECT_LOCK, appName);
|
||||||
|
boolean lockStatus = lockService.lock(lockName);
|
||||||
|
if (!lockStatus) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
}catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
|
||||||
|
// 可能上一台机器已经完成了Server选举,需要再次判断
|
||||||
|
AppInfoDO appInfo = appInfoRepository.findByAppName(appName);
|
||||||
|
if (isActive(appInfo.getCurrentServer())) {
|
||||||
|
return appInfo.getCurrentServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 篡位,本机作为Server
|
||||||
|
appInfo.setCurrentServer(OhMyServer.getActorSystemAddress());
|
||||||
|
appInfo.setGmtModified(new Date());
|
||||||
|
|
||||||
|
appInfoRepository.saveAndFlush(appInfo);
|
||||||
|
return appInfo.getCurrentServer();
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.warn("[ServerSelectService] write new server to db failed for app {}.", appName);
|
||||||
|
}finally {
|
||||||
|
lockService.unlock(lockName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("server elect failed for app " + appName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActive(String serverAddress) {
|
||||||
|
if (StringUtils.isEmpty(serverAddress)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Ping ping = new Ping();
|
||||||
|
ping.setCurrentTime(System.currentTimeMillis());
|
||||||
|
|
||||||
|
ActorSelection serverActor = OhMyServer.getServerActor(serverAddress);
|
||||||
|
try {
|
||||||
|
CompletionStage<Object> askCS = Patterns.ask(serverActor, ping, Duration.ofMillis(PING_TIMEOUT_MS));
|
||||||
|
AskResponse response = (AskResponse) askCS.toCompletableFuture().get(PING_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
|
return response.isSuccess();
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.warn("[ServerSelectService] server({}) was down, try to elect a new server.", serverAddress);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,52 +0,0 @@
|
|||||||
package com.github.kfcfans.oms.server.service.impl;
|
|
||||||
|
|
||||||
import com.github.kfcfans.common.utils.CommonUtils;
|
|
||||||
import com.github.kfcfans.common.utils.NetUtils;
|
|
||||||
import com.github.kfcfans.oms.server.persistence.model.OmsLockDO;
|
|
||||||
import com.github.kfcfans.oms.server.persistence.repository.OmsLockRepository;
|
|
||||||
import com.github.kfcfans.oms.server.service.LockService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 基于数据库实现分布式锁
|
|
||||||
*
|
|
||||||
* @author tjq
|
|
||||||
* @since 2020/4/2
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class DatabaseLockService implements LockService {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private OmsLockRepository omsLockRepository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean lock(String name) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
OmsLockDO lock = new OmsLockDO(name, NetUtils.getLocalHost());
|
|
||||||
omsLockRepository.saveAndFlush(lock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}catch (DataIntegrityViolationException ignore) {
|
|
||||||
log.info("[DatabaseLockService] other thread get the lock {}.", name);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("[DatabaseLockService] lock {} failed.", name, e);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unlock(String name) {
|
|
||||||
try {
|
|
||||||
CommonUtils.executeWithRetry0(() -> omsLockRepository.deleteByLockName(name));
|
|
||||||
}catch (Exception e) {
|
|
||||||
log.error("[DatabaseLockService] unlock {} failed.", name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.github.kfcfans.oms.server.service.lock;
|
||||||
|
|
||||||
|
import com.github.kfcfans.common.utils.CommonUtils;
|
||||||
|
import com.github.kfcfans.common.utils.NetUtils;
|
||||||
|
import com.github.kfcfans.oms.server.persistence.model.OmsLockDO;
|
||||||
|
import com.github.kfcfans.oms.server.persistence.repository.OmsLockRepository;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于数据库实现的分布式锁
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2020/4/5
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DatabaseLockService implements LockService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OmsLockRepository omsLockRepository;
|
||||||
|
|
||||||
|
private Map<String, AtomicInteger> lockName2FailedTimes = Maps.newConcurrentMap();
|
||||||
|
private static final int MAX_FAILED_NUM = 5;
|
||||||
|
// 最长持有锁30秒
|
||||||
|
private static final long LOCK_TIMEOUT_MS = 30000;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean lock(String name) {
|
||||||
|
|
||||||
|
AtomicInteger failedCount = lockName2FailedTimes.computeIfAbsent(name, ignore -> new AtomicInteger(0));
|
||||||
|
OmsLockDO newLock = new OmsLockDO(name, NetUtils.getLocalHost());
|
||||||
|
try {
|
||||||
|
omsLockRepository.saveAndFlush(newLock);
|
||||||
|
failedCount.set(0);
|
||||||
|
return true;
|
||||||
|
}catch (DataIntegrityViolationException ignore) {
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.warn("[DatabaseLockService] write lock to database failed, lockName = {}.", name, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连续失败一段时间,需要判断是否为锁释放失败的情况
|
||||||
|
if (failedCount.incrementAndGet() > MAX_FAILED_NUM) {
|
||||||
|
|
||||||
|
OmsLockDO omsLockDO = omsLockRepository.findByLockName(name);
|
||||||
|
long lockedMillions = System.currentTimeMillis() - omsLockDO.getGmtCreate().getTime();
|
||||||
|
if (lockedMillions > LOCK_TIMEOUT_MS) {
|
||||||
|
|
||||||
|
log.warn("[DatabaseLockService] The lock({}) already timeout, will be deleted now.", omsLockDO);
|
||||||
|
unlock(name);
|
||||||
|
} else {
|
||||||
|
failedCount.set(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unlock(String name) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
CommonUtils.executeWithRetry0(() -> omsLockRepository.deleteByLockName(name));
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("[DatabaseLockService] unlock {} failed.", name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package com.github.kfcfans.oms.server.service;
|
package com.github.kfcfans.oms.server.service.lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 锁服务
|
* 锁服务,所有方法都不允许抛出任何异常!
|
||||||
*
|
*
|
||||||
* @author tjq
|
* @author tjq
|
||||||
* @since 2020/4/2
|
* @since 2020/4/2
|
@ -19,6 +19,6 @@ public class ControllerExceptionHandler {
|
|||||||
@ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
public ResultDTO<Void> exceptionHandler(Exception e) {
|
public ResultDTO<Void> exceptionHandler(Exception e) {
|
||||||
log.error("[ControllerException] http request failed.", e);
|
log.error("[ControllerException] http request failed.", e);
|
||||||
return ResultDTO.failed(e);
|
return ResultDTO.failed(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.github.kfcfans.oms.server.web.controller;
|
||||||
|
|
||||||
|
import com.github.kfcfans.oms.server.service.ha.ServerSelectService;
|
||||||
|
import com.github.kfcfans.oms.server.web.ResultDTO;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理内部请求的 Controller
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2020/4/4
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/server")
|
||||||
|
public class ServerController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ServerSelectService serverSelectService;
|
||||||
|
|
||||||
|
@GetMapping("/acquire")
|
||||||
|
public ResultDTO<String> acquireServer(String appName) {
|
||||||
|
String server = serverSelectService.getServer(appName);
|
||||||
|
return ResultDTO.success(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -11,4 +11,7 @@ spring.datasource.hikari.maximum-pool-size=20
|
|||||||
spring.datasource.hikari.minimum-idle=5
|
spring.datasource.hikari.minimum-idle=5
|
||||||
# JPA 相关配置
|
# JPA 相关配置
|
||||||
spring.jpa.show-sql=true
|
spring.jpa.show-sql=true
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
|
||||||
|
# ZooKeeper(多值逗号分割)
|
||||||
|
zookeeper.address=115.159.215.229:2181
|
@ -1,6 +1,6 @@
|
|||||||
package com.github.kfcfans.oms.server.test;
|
package com.github.kfcfans.oms.server.test;
|
||||||
|
|
||||||
import com.github.kfcfans.oms.server.service.LockService;
|
import com.github.kfcfans.oms.server.service.lock.LockService;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user