30 changed files with 859 additions and 527 deletions
@ -1,8 +0,0 @@ |
|||||
# Default ignored files |
|
||||
/shelf/ |
|
||||
/workspace.xml |
|
||||
# Datasource local storage ignored files |
|
||||
/dataSources/ |
|
||||
/dataSources.local.xml |
|
||||
# Editor-based HTTP Client requests |
|
||||
/httpRequests/ |
|
@ -1,6 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<project version="4"> |
|
||||
<component name="CompilerConfiguration"> |
|
||||
<bytecodeTargetLevel target="8" /> |
|
||||
</component> |
|
||||
</project> |
|
@ -1,6 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<project version="4"> |
|
||||
<component name="ProjectDictionaryState"> |
|
||||
<dictionary name="mima0000" /> |
|
||||
</component> |
|
||||
</project> |
|
@ -1,37 +0,0 @@ |
|||||
<component name="InspectionProjectProfileManager"> |
|
||||
<profile version="1.0"> |
|
||||
<option name="myName" value="Project Default" /> |
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" /> |
|
||||
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true"> |
|
||||
<option name="TOP_LEVEL_CLASS_OPTIONS"> |
|
||||
<value> |
|
||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
|
||||
<option name="REQUIRED_TAGS" value="" /> |
|
||||
</value> |
|
||||
</option> |
|
||||
<option name="INNER_CLASS_OPTIONS"> |
|
||||
<value> |
|
||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
|
||||
<option name="REQUIRED_TAGS" value="" /> |
|
||||
</value> |
|
||||
</option> |
|
||||
<option name="METHOD_OPTIONS"> |
|
||||
<value> |
|
||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
|
||||
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" /> |
|
||||
</value> |
|
||||
</option> |
|
||||
<option name="FIELD_OPTIONS"> |
|
||||
<value> |
|
||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
|
||||
<option name="REQUIRED_TAGS" value="" /> |
|
||||
</value> |
|
||||
</option> |
|
||||
<option name="IGNORE_DEPRECATED" value="false" /> |
|
||||
<option name="IGNORE_JAVADOC_PERIOD" value="true" /> |
|
||||
<option name="IGNORE_DUPLICATED_THROWS" value="false" /> |
|
||||
<option name="IGNORE_POINT_TO_ITSELF" value="false" /> |
|
||||
<option name="myAdditionalJavadocTags" value="date" /> |
|
||||
</inspection_tool> |
|
||||
</profile> |
|
||||
</component> |
|
@ -1,8 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<project version="4"> |
|
||||
<component name="ProjectModuleManager"> |
|
||||
<modules> |
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/nl-sso-server.iml" filepath="$PROJECT_DIR$/.idea/nl-sso-server.iml" /> |
|
||||
</modules> |
|
||||
</component> |
|
||||
</project> |
|
@ -1,9 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<module type="JAVA_MODULE" version="4"> |
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true"> |
|
||||
<exclude-output /> |
|
||||
<content url="file://$MODULE_DIR$" /> |
|
||||
<orderEntry type="inheritedJdk" /> |
|
||||
<orderEntry type="sourceFolder" forTests="false" /> |
|
||||
</component> |
|
||||
</module> |
|
@ -1,6 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<project version="4"> |
|
||||
<component name="VcsDirectoryMappings"> |
|
||||
<mapping directory="" vcs="Git" /> |
|
||||
</component> |
|
||||
</project> |
|
@ -0,0 +1,42 @@ |
|||||
|
package org.nl.config; |
||||
|
|
||||
|
import com.dtp.core.support.ThreadPoolBuilder; |
||||
|
import com.dtp.core.support.ThreadPoolCreator; |
||||
|
import com.dtp.core.thread.DtpExecutor; |
||||
|
import org.springframework.boot.web.servlet.server.ServletWebServerFactory; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
/** |
||||
|
* @author ldjun |
||||
|
* @version 1.0 |
||||
|
* @date 2023年01月13日 14:30 |
||||
|
* @desc desc |
||||
|
*/ |
||||
|
@Configuration |
||||
|
public class DtpConfig { |
||||
|
|
||||
|
/** |
||||
|
* 通过{@link ThreadPoolCreator} 快速创建一些简单配置的动态线程池 |
||||
|
* tips: 建议直接在配置中心配置就行,不用@Bean声明 |
||||
|
* |
||||
|
* @return 线程池实例 |
||||
|
*/ |
||||
|
@Bean |
||||
|
public DtpExecutor dtpExecutor1() { |
||||
|
|
||||
|
return ThreadPoolBuilder.newBuilder() |
||||
|
.threadPoolName("dtpExecutor1") |
||||
|
.corePoolSize(1) |
||||
|
.maximumPoolSize(1) |
||||
|
.queueCapacity(1) |
||||
|
.ioIntensive(true) |
||||
|
.buildDynamic(); |
||||
|
} |
||||
|
@Bean |
||||
|
public Object tomcatServletWebServerFactory(ServletWebServerFactory webServerFactory) { |
||||
|
return new Object(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -1,40 +0,0 @@ |
|||||
package org.nl.modules.loki.rest; |
|
||||
|
|
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
import io.swagger.annotations.Api; |
|
||||
import io.swagger.annotations.ApiOperation; |
|
||||
import lombok.RequiredArgsConstructor; |
|
||||
import lombok.extern.slf4j.Slf4j; |
|
||||
import org.nl.modules.common.annotation.RateLimiter; |
|
||||
import org.nl.modules.loki.service.LokiService; |
|
||||
import org.springframework.http.HttpStatus; |
|
||||
import org.springframework.http.ResponseEntity; |
|
||||
import org.springframework.web.bind.annotation.*; |
|
||||
|
|
||||
/** |
|
||||
* @Author: lyd |
|
||||
* @Description: 日志监控 |
|
||||
* @Date: 2022-08-15 |
|
||||
*/ |
|
||||
@RestController |
|
||||
@RequiredArgsConstructor |
|
||||
@Api(tags = "日志监控") |
|
||||
@RequestMapping("/api/loki") |
|
||||
@Slf4j |
|
||||
public class LokiController { |
|
||||
|
|
||||
private final LokiService lokiService; |
|
||||
|
|
||||
@GetMapping("/labels/values") |
|
||||
@ApiOperation("获取标签") |
|
||||
public ResponseEntity<Object> labelsValues() { |
|
||||
return new ResponseEntity<>(lokiService.getLabelsValues(), HttpStatus.OK); |
|
||||
} |
|
||||
|
|
||||
@PostMapping("/logs") |
|
||||
@ApiOperation("获取日志") |
|
||||
@RateLimiter(value = 1, timeout = 300) // 限流
|
|
||||
public ResponseEntity<Object> getLogData(@RequestBody JSONObject json) { |
|
||||
return new ResponseEntity<>(lokiService.getLogData(json), HttpStatus.OK); |
|
||||
} |
|
||||
} |
|
@ -1,25 +0,0 @@ |
|||||
package org.nl.modules.loki.service; |
|
||||
|
|
||||
import com.alibaba.fastjson.JSONArray; |
|
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
|
|
||||
/** |
|
||||
* @Author: lyd |
|
||||
* @Description: 服务类 |
|
||||
* @Date: 2022-08-15 |
|
||||
*/ |
|
||||
public interface LokiService { |
|
||||
|
|
||||
/** |
|
||||
* 获取日志信息 |
|
||||
* @param json |
|
||||
* @return |
|
||||
*/ |
|
||||
JSONObject getLogData(JSONObject json); |
|
||||
|
|
||||
/** |
|
||||
* 获取labels和values树 |
|
||||
* @return |
|
||||
*/ |
|
||||
JSONArray getLabelsValues(); |
|
||||
} |
|
@ -1,113 +0,0 @@ |
|||||
package org.nl.modules.loki.service.impl; |
|
||||
|
|
||||
import cn.hutool.core.util.CharsetUtil; |
|
||||
import cn.hutool.http.HttpUtil; |
|
||||
import com.alibaba.fastjson.JSONArray; |
|
||||
import com.alibaba.fastjson.JSONObject; |
|
||||
import lombok.RequiredArgsConstructor; |
|
||||
import org.nl.modules.loki.service.LokiService; |
|
||||
import org.springframework.beans.factory.annotation.Value; |
|
||||
import org.springframework.stereotype.Service; |
|
||||
|
|
||||
/** |
|
||||
* @Author: lyd |
|
||||
* @Description: 实现类 |
|
||||
* @Date: 2022-08-15 |
|
||||
*/ |
|
||||
@Service |
|
||||
@RequiredArgsConstructor |
|
||||
public class LokiServiceImpl implements LokiService { |
|
||||
|
|
||||
@Value("${loki.url}") |
|
||||
private String lokiUrl; |
|
||||
|
|
||||
@Value("${loki.systemName}") |
|
||||
private String systemName; |
|
||||
|
|
||||
@Override |
|
||||
public JSONObject getLogData(JSONObject json) { |
|
||||
String logLabel = ""; |
|
||||
String logLabelValue = ""; |
|
||||
Long start = 0L; |
|
||||
Long end = 0L; |
|
||||
String text = ""; |
|
||||
String limit = "100"; |
|
||||
String direction = "backward"; |
|
||||
if (json.get("logLabel") != null) logLabel = json.getString("logLabel"); |
|
||||
if (json.get("logLabelValue") != null) logLabelValue = json.getString("logLabelValue"); |
|
||||
if (json.get("text") != null) text = json.getString("text"); |
|
||||
if (json.get("start") != null) start = json.getLong("start"); |
|
||||
if (json.get("end") != null) end = json.getLong("end"); |
|
||||
if (json.get("limits") != null) limit = json.getString("limits"); |
|
||||
if (json.get("direction") != null) direction = json.getString("direction"); |
|
||||
/** |
|
||||
* 组织参数 |
|
||||
* 纳秒数 |
|
||||
* 1660037391880000000 |
|
||||
* 1641453208415000000 |
|
||||
* http://localhost:3100/loki/api/v1/query_range?query={host="localhost"} |= ``&limit=1500&start=1641453208415000000&end=1660027623419419002
|
|
||||
*/ |
|
||||
JSONObject parse = null; |
|
||||
String query = lokiUrl + "/query_range?query={system=\"" + systemName + "\", " + logLabel + "=\"" + logLabelValue + "\"} |= `" + text + "`"; |
|
||||
String result = ""; |
|
||||
if (start==0L) { |
|
||||
result = HttpUtil.get(query + "&limit=" + limit + "&direction=" + direction, CharsetUtil.CHARSET_UTF_8); |
|
||||
} else { |
|
||||
result = HttpUtil.get(query + "&limit=" + limit + "&start=" + start + "&end=" + end + "&direction=" + direction, CharsetUtil.CHARSET_UTF_8); |
|
||||
} |
|
||||
try { |
|
||||
parse = (JSONObject) JSONObject.parse(result); |
|
||||
} catch (Exception e) { |
|
||||
// reslut的值可能为:too many outstanding requests,无法转化成Json
|
|
||||
System.out.println("reslut:" + result); |
|
||||
// e.printStackTrace();
|
|
||||
} |
|
||||
return parse; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 获取labels和values树 |
|
||||
* |
|
||||
* @return |
|
||||
*/ |
|
||||
@Override |
|
||||
public JSONArray getLabelsValues() { |
|
||||
/** |
|
||||
* [{ |
|
||||
* label: |
|
||||
* value: |
|
||||
* children:[{ |
|
||||
* label |
|
||||
* value |
|
||||
* }] |
|
||||
* }] |
|
||||
*/ |
|
||||
JSONArray result = new JSONArray(); |
|
||||
// 获取所有标签
|
|
||||
String labelString = HttpUtil.get(lokiUrl + "/labels", CharsetUtil.CHARSET_UTF_8); |
|
||||
JSONObject parse = (JSONObject) JSONObject.parse(labelString); |
|
||||
JSONArray labels = parse.getJSONArray("data"); |
|
||||
for (int i=0; i<labels.size(); i++) { |
|
||||
// 获取标签下的所有值
|
|
||||
String valueString = HttpUtil.get(lokiUrl + "/label/" + labels.getString(i) + "/values", CharsetUtil.CHARSET_UTF_8); |
|
||||
JSONObject parse2 = (JSONObject) JSONObject.parse(valueString); |
|
||||
JSONArray values = parse2.getJSONArray("data"); |
|
||||
JSONArray children = new JSONArray(); |
|
||||
// 组成树形状态 两级
|
|
||||
for (int j=0; j<values.size(); j++) { |
|
||||
JSONObject leaf = new JSONObject(); |
|
||||
leaf.put("label", values.getString(j)); |
|
||||
leaf.put("value", values.getString(j)); |
|
||||
children.add(leaf); |
|
||||
} |
|
||||
|
|
||||
JSONObject node = new JSONObject(); |
|
||||
node.put("label", labels.getString(i)); |
|
||||
node.put("value", labels.getString(i)); |
|
||||
node.put("children", children); |
|
||||
result.add(node); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
} |
|
@ -0,0 +1,585 @@ |
|||||
|
package org.nl.system.service.quartz; |
||||
|
|
||||
|
import org.quartz.SchedulerConfigException; |
||||
|
import org.quartz.spi.ThreadPool; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
|
||||
|
import java.util.Iterator; |
||||
|
import java.util.LinkedList; |
||||
|
import java.util.List; |
||||
|
import java.util.concurrent.atomic.AtomicBoolean; |
||||
|
|
||||
|
/** |
||||
|
* quartz自定义线程池 |
||||
|
*/ |
||||
|
public class SimpleThreadPool implements ThreadPool { |
||||
|
|
||||
|
/* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
* |
||||
|
* Data members. |
||||
|
* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
*/ |
||||
|
|
||||
|
private int count = -1; |
||||
|
|
||||
|
private int prio = Thread.NORM_PRIORITY; |
||||
|
|
||||
|
private boolean isShutdown = false; |
||||
|
private boolean handoffPending = false; |
||||
|
|
||||
|
private boolean inheritLoader = false; |
||||
|
|
||||
|
private boolean inheritGroup = true; |
||||
|
|
||||
|
private boolean makeThreadsDaemons = false; |
||||
|
|
||||
|
private ThreadGroup threadGroup; |
||||
|
|
||||
|
private final Object nextRunnableLock = new Object(); |
||||
|
|
||||
|
private List<WorkerThread> workers; |
||||
|
private LinkedList<WorkerThread> availWorkers = new LinkedList<WorkerThread>(); |
||||
|
private LinkedList<WorkerThread> busyWorkers = new LinkedList<WorkerThread>(); |
||||
|
|
||||
|
private String threadNamePrefix; |
||||
|
|
||||
|
private final Logger log = LoggerFactory.getLogger(getClass()); |
||||
|
|
||||
|
private String schedulerInstanceName; |
||||
|
|
||||
|
/* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
* |
||||
|
* Constructors. |
||||
|
* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Create a new (unconfigured) <code>SimpleThreadPool</code>. |
||||
|
* </p> |
||||
|
* |
||||
|
* @see #setThreadCount(int) |
||||
|
* @see #setThreadPriority(int) |
||||
|
*/ |
||||
|
public SimpleThreadPool() { |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Create a new <code>SimpleThreadPool</code> with the specified number |
||||
|
* of <code>Thread</code> s that have the given priority. |
||||
|
* </p> |
||||
|
* |
||||
|
* @param threadCount |
||||
|
* the number of worker <code>Threads</code> in the pool, must |
||||
|
* be > 0. |
||||
|
* @param threadPriority |
||||
|
* the thread priority for the worker threads. |
||||
|
* |
||||
|
* @see Thread |
||||
|
*/ |
||||
|
public SimpleThreadPool(int threadCount, int threadPriority) { |
||||
|
setThreadCount(threadCount); |
||||
|
setThreadPriority(threadPriority); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
* |
||||
|
* Interface. |
||||
|
* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
*/ |
||||
|
|
||||
|
public Logger getLog() { |
||||
|
return log; |
||||
|
} |
||||
|
|
||||
|
public int getPoolSize() { |
||||
|
return getThreadCount(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Set the number of worker threads in the pool - has no effect after |
||||
|
* <code>initialize()</code> has been called. |
||||
|
* </p> |
||||
|
*/ |
||||
|
public void setThreadCount(int count) { |
||||
|
this.count = count; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Get the number of worker threads in the pool. |
||||
|
* </p> |
||||
|
*/ |
||||
|
public int getThreadCount() { |
||||
|
return count; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Set the thread priority of worker threads in the pool - has no effect |
||||
|
* after <code>initialize()</code> has been called. |
||||
|
* </p> |
||||
|
*/ |
||||
|
public void setThreadPriority(int prio) { |
||||
|
this.prio = prio; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Get the thread priority of worker threads in the pool. |
||||
|
* </p> |
||||
|
*/ |
||||
|
public int getThreadPriority() { |
||||
|
return prio; |
||||
|
} |
||||
|
|
||||
|
public void setThreadNamePrefix(String prfx) { |
||||
|
this.threadNamePrefix = prfx; |
||||
|
} |
||||
|
|
||||
|
public String getThreadNamePrefix() { |
||||
|
return threadNamePrefix; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return Returns the |
||||
|
* threadsInheritContextClassLoaderOfInitializingThread. |
||||
|
*/ |
||||
|
public boolean isThreadsInheritContextClassLoaderOfInitializingThread() { |
||||
|
return inheritLoader; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param inheritLoader |
||||
|
* The threadsInheritContextClassLoaderOfInitializingThread to |
||||
|
* set. |
||||
|
*/ |
||||
|
public void setThreadsInheritContextClassLoaderOfInitializingThread( |
||||
|
boolean inheritLoader) { |
||||
|
this.inheritLoader = inheritLoader; |
||||
|
} |
||||
|
|
||||
|
public boolean isThreadsInheritGroupOfInitializingThread() { |
||||
|
return inheritGroup; |
||||
|
} |
||||
|
|
||||
|
public void setThreadsInheritGroupOfInitializingThread( |
||||
|
boolean inheritGroup) { |
||||
|
this.inheritGroup = inheritGroup; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* @return Returns the value of makeThreadsDaemons. |
||||
|
*/ |
||||
|
public boolean isMakeThreadsDaemons() { |
||||
|
return makeThreadsDaemons; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param makeThreadsDaemons |
||||
|
* The value of makeThreadsDaemons to set. |
||||
|
*/ |
||||
|
public void setMakeThreadsDaemons(boolean makeThreadsDaemons) { |
||||
|
this.makeThreadsDaemons = makeThreadsDaemons; |
||||
|
} |
||||
|
|
||||
|
public void setInstanceId(String schedInstId) { |
||||
|
} |
||||
|
|
||||
|
public void setInstanceName(String schedName) { |
||||
|
schedulerInstanceName = schedName; |
||||
|
} |
||||
|
|
||||
|
public void initialize() throws SchedulerConfigException { |
||||
|
|
||||
|
if(workers != null && workers.size() > 0) // already initialized...
|
||||
|
return; |
||||
|
|
||||
|
if (count <= 0) { |
||||
|
throw new SchedulerConfigException( |
||||
|
"Thread count must be > 0"); |
||||
|
} |
||||
|
if (prio <= 0 || prio > 9) { |
||||
|
throw new SchedulerConfigException( |
||||
|
"Thread priority must be > 0 and <= 9"); |
||||
|
} |
||||
|
|
||||
|
if(isThreadsInheritGroupOfInitializingThread()) { |
||||
|
threadGroup = Thread.currentThread().getThreadGroup(); |
||||
|
} else { |
||||
|
// follow the threadGroup tree to the root thread group.
|
||||
|
threadGroup = Thread.currentThread().getThreadGroup(); |
||||
|
ThreadGroup parent = threadGroup; |
||||
|
while ( !parent.getName().equals("main") ) { |
||||
|
threadGroup = parent; |
||||
|
parent = threadGroup.getParent(); |
||||
|
} |
||||
|
threadGroup = new ThreadGroup(parent, schedulerInstanceName + "-SimpleThreadPool"); |
||||
|
if (isMakeThreadsDaemons()) { |
||||
|
threadGroup.setDaemon(true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (isThreadsInheritContextClassLoaderOfInitializingThread()) { |
||||
|
getLog().info( |
||||
|
"Job execution threads will use class loader of thread: " |
||||
|
+ Thread.currentThread().getName()); |
||||
|
} |
||||
|
|
||||
|
// create the worker threads and start them
|
||||
|
Iterator<WorkerThread> workerThreads = createWorkerThreads(count).iterator(); |
||||
|
while(workerThreads.hasNext()) { |
||||
|
WorkerThread wt = workerThreads.next(); |
||||
|
wt.start(); |
||||
|
availWorkers.add(wt); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected List<WorkerThread> createWorkerThreads(int createCount) { |
||||
|
workers = new LinkedList<WorkerThread>(); |
||||
|
for (int i = 1; i<= createCount; ++i) { |
||||
|
String threadPrefix = getThreadNamePrefix(); |
||||
|
if (threadPrefix == null) { |
||||
|
threadPrefix = schedulerInstanceName + "_Worker"; |
||||
|
} |
||||
|
WorkerThread wt = new WorkerThread(this, threadGroup, |
||||
|
threadPrefix + "-" + i, |
||||
|
getThreadPriority(), |
||||
|
isMakeThreadsDaemons()); |
||||
|
if (isThreadsInheritContextClassLoaderOfInitializingThread()) { |
||||
|
wt.setContextClassLoader(Thread.currentThread() |
||||
|
.getContextClassLoader()); |
||||
|
} |
||||
|
workers.add(wt); |
||||
|
} |
||||
|
|
||||
|
return workers; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Terminate any worker threads in this thread group. |
||||
|
* </p> |
||||
|
* |
||||
|
* <p> |
||||
|
* Jobs currently in progress will complete. |
||||
|
* </p> |
||||
|
*/ |
||||
|
public void shutdown() { |
||||
|
shutdown(true); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Terminate any worker threads in this thread group. |
||||
|
* </p> |
||||
|
* |
||||
|
* <p> |
||||
|
* Jobs currently in progress will complete. |
||||
|
* </p> |
||||
|
*/ |
||||
|
public void shutdown(boolean waitForJobsToComplete) { |
||||
|
|
||||
|
synchronized (nextRunnableLock) { |
||||
|
getLog().debug("Shutting down threadpool..."); |
||||
|
|
||||
|
isShutdown = true; |
||||
|
|
||||
|
if(workers == null) // case where the pool wasn't even initialize()ed
|
||||
|
return; |
||||
|
|
||||
|
// signal each worker thread to shut down
|
||||
|
Iterator<WorkerThread> workerThreads = workers.iterator(); |
||||
|
while(workerThreads.hasNext()) { |
||||
|
WorkerThread wt = workerThreads.next(); |
||||
|
wt.shutdown(); |
||||
|
availWorkers.remove(wt); |
||||
|
} |
||||
|
|
||||
|
// Give waiting (wait(1000)) worker threads a chance to shut down.
|
||||
|
// Active worker threads will shut down after finishing their
|
||||
|
// current job.
|
||||
|
nextRunnableLock.notifyAll(); |
||||
|
|
||||
|
if (waitForJobsToComplete == true) { |
||||
|
|
||||
|
boolean interrupted = false; |
||||
|
try { |
||||
|
// wait for hand-off in runInThread to complete...
|
||||
|
while(handoffPending) { |
||||
|
try { |
||||
|
nextRunnableLock.wait(100); |
||||
|
} catch(InterruptedException _) { |
||||
|
interrupted = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Wait until all worker threads are shut down
|
||||
|
while (busyWorkers.size() > 0) { |
||||
|
WorkerThread wt = (WorkerThread) busyWorkers.getFirst(); |
||||
|
try { |
||||
|
getLog().debug( |
||||
|
"Waiting for thread " + wt.getName() |
||||
|
+ " to shut down"); |
||||
|
|
||||
|
// note: with waiting infinite time the
|
||||
|
// application may appear to 'hang'.
|
||||
|
nextRunnableLock.wait(2000); |
||||
|
} catch (InterruptedException _) { |
||||
|
interrupted = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
workerThreads = workers.iterator(); |
||||
|
while(workerThreads.hasNext()) { |
||||
|
WorkerThread wt = (WorkerThread) workerThreads.next(); |
||||
|
try { |
||||
|
wt.join(); |
||||
|
workerThreads.remove(); |
||||
|
} catch (InterruptedException _) { |
||||
|
interrupted = true; |
||||
|
} |
||||
|
} |
||||
|
} finally { |
||||
|
if (interrupted) { |
||||
|
Thread.currentThread().interrupt(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
getLog().debug("No executing jobs remaining, all threads stopped."); |
||||
|
} |
||||
|
getLog().debug("Shutdown of threadpool complete."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Run the given <code>Runnable</code> object in the next available |
||||
|
* <code>Thread</code>. If while waiting the thread pool is asked to |
||||
|
* shut down, the Runnable is executed immediately within a new additional |
||||
|
* thread. |
||||
|
* </p> |
||||
|
* |
||||
|
* @param runnable |
||||
|
* the <code>Runnable</code> to be added. |
||||
|
*/ |
||||
|
public boolean runInThread(Runnable runnable) { |
||||
|
if (runnable == null) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
synchronized (nextRunnableLock) { |
||||
|
|
||||
|
handoffPending = true; |
||||
|
|
||||
|
// Wait until a worker thread is available
|
||||
|
while ((availWorkers.size() < 1) && !isShutdown) { |
||||
|
try { |
||||
|
nextRunnableLock.wait(500); |
||||
|
} catch (InterruptedException ignore) { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!isShutdown) { |
||||
|
WorkerThread wt = (WorkerThread)availWorkers.removeFirst(); |
||||
|
busyWorkers.add(wt); |
||||
|
wt.run(runnable); |
||||
|
} else { |
||||
|
// If the thread pool is going down, execute the Runnable
|
||||
|
// within a new additional worker thread (no thread from the pool).
|
||||
|
WorkerThread wt = new WorkerThread(this, threadGroup, |
||||
|
"WorkerThread-LastJob", prio, isMakeThreadsDaemons(), runnable); |
||||
|
busyWorkers.add(wt); |
||||
|
workers.add(wt); |
||||
|
wt.start(); |
||||
|
} |
||||
|
nextRunnableLock.notifyAll(); |
||||
|
handoffPending = false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
public int blockForAvailableThreads() { |
||||
|
synchronized(nextRunnableLock) { |
||||
|
|
||||
|
while((availWorkers.size() < 1 || handoffPending) && !isShutdown) { |
||||
|
try { |
||||
|
nextRunnableLock.wait(500); |
||||
|
} catch (InterruptedException ignore) { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return availWorkers.size(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected void makeAvailable(WorkerThread wt) { |
||||
|
synchronized(nextRunnableLock) { |
||||
|
if(!isShutdown) { |
||||
|
availWorkers.add(wt); |
||||
|
} |
||||
|
busyWorkers.remove(wt); |
||||
|
nextRunnableLock.notifyAll(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected void clearFromBusyWorkersList(WorkerThread wt) { |
||||
|
synchronized(nextRunnableLock) { |
||||
|
busyWorkers.remove(wt); |
||||
|
nextRunnableLock.notifyAll(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
* |
||||
|
* WorkerThread Class. |
||||
|
* |
||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* A Worker loops, waiting to execute tasks. |
||||
|
* </p> |
||||
|
*/ |
||||
|
class WorkerThread extends Thread { |
||||
|
|
||||
|
private final Object lock = new Object(); |
||||
|
|
||||
|
// A flag that signals the WorkerThread to terminate.
|
||||
|
private AtomicBoolean run = new AtomicBoolean(true); |
||||
|
|
||||
|
private SimpleThreadPool tp; |
||||
|
|
||||
|
private Runnable runnable = null; |
||||
|
|
||||
|
private boolean runOnce = false; |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Create a worker thread and start it. Waiting for the next Runnable, |
||||
|
* executing it, and waiting for the next Runnable, until the shutdown |
||||
|
* flag is set. |
||||
|
* </p> |
||||
|
*/ |
||||
|
WorkerThread(SimpleThreadPool tp, ThreadGroup threadGroup, String name, |
||||
|
int prio, boolean isDaemon) { |
||||
|
|
||||
|
this(tp, threadGroup, name, prio, isDaemon, null); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Create a worker thread, start it, execute the runnable and terminate |
||||
|
* the thread (one time execution). |
||||
|
* </p> |
||||
|
*/ |
||||
|
WorkerThread(SimpleThreadPool tp, ThreadGroup threadGroup, String name, |
||||
|
int prio, boolean isDaemon, Runnable runnable) { |
||||
|
|
||||
|
super(threadGroup, name); |
||||
|
this.tp = tp; |
||||
|
this.runnable = runnable; |
||||
|
if(runnable != null) |
||||
|
runOnce = true; |
||||
|
setPriority(prio); |
||||
|
setDaemon(isDaemon); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Signal the thread that it should terminate. |
||||
|
* </p> |
||||
|
*/ |
||||
|
void shutdown() { |
||||
|
run.set(false); |
||||
|
} |
||||
|
|
||||
|
public void run(Runnable newRunnable) { |
||||
|
synchronized(lock) { |
||||
|
if(runnable != null) { |
||||
|
throw new IllegalStateException("Already running a Runnable!"); |
||||
|
} |
||||
|
|
||||
|
runnable = newRunnable; |
||||
|
lock.notifyAll(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* <p> |
||||
|
* Loop, executing targets as they are received. |
||||
|
* </p> |
||||
|
*/ |
||||
|
@Override |
||||
|
public void run() { |
||||
|
boolean ran = false; |
||||
|
|
||||
|
while (run.get()) { |
||||
|
try { |
||||
|
synchronized(lock) { |
||||
|
while (runnable == null && run.get()) { |
||||
|
lock.wait(500); |
||||
|
} |
||||
|
|
||||
|
if (runnable != null) { |
||||
|
ran = true; |
||||
|
runnable.run(); |
||||
|
} |
||||
|
} |
||||
|
} catch (InterruptedException unblock) { |
||||
|
// do nothing (loop will terminate if shutdown() was called
|
||||
|
try { |
||||
|
getLog().error("Worker thread was interrupt()'ed.", unblock); |
||||
|
} catch(Exception e) { |
||||
|
// ignore to help with a tomcat glitch
|
||||
|
} |
||||
|
} catch (Throwable exceptionInRunnable) { |
||||
|
try { |
||||
|
getLog().error("Error while executing the Runnable: ", |
||||
|
exceptionInRunnable); |
||||
|
} catch(Exception e) { |
||||
|
// ignore to help with a tomcat glitch
|
||||
|
} |
||||
|
} finally { |
||||
|
synchronized(lock) { |
||||
|
runnable = null; |
||||
|
} |
||||
|
// repair the thread in case the runnable mucked it up...
|
||||
|
if(getPriority() != tp.getThreadPriority()) { |
||||
|
setPriority(tp.getThreadPriority()); |
||||
|
} |
||||
|
|
||||
|
if (runOnce) { |
||||
|
run.set(false); |
||||
|
clearFromBusyWorkersList(this); |
||||
|
} else if(ran) { |
||||
|
ran = false; |
||||
|
makeAvailable(this); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//if (log.isDebugEnabled())
|
||||
|
try { |
||||
|
getLog().debug("WorkerThread is shut down."); |
||||
|
} catch(Exception e) { |
||||
|
// ignore to help with a tomcat glitch
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -1,120 +0,0 @@ |
|||||
# 端口 |
|
||||
server: |
|
||||
port: 9000 |
|
||||
|
|
||||
# Sa-Token 配置 |
|
||||
sa-token: |
|
||||
# ------- SSO-模式一相关配置 (非模式一不需要配置) |
|
||||
|
|
||||
# 配置 Cookie 作用域 |
|
||||
|
|
||||
# ------- SSO-模式二相关配置 |
|
||||
sso: |
|
||||
# Ticket有效期 (单位: 秒),默认五分钟 |
|
||||
ticket-timeout: 300 |
|
||||
# 所有允许的授权回调地址比较重要 |
|
||||
allow-url: "*" |
|
||||
# 是否打开单点注销功能 |
|
||||
is-slo: true |
|
||||
# ------- SSO-模式三相关配置 (下面的配置在SSO模式三并且 is-slo=true 时打开) |
|
||||
# # 是否打开模式三 |
|
||||
isHttp: true |
|
||||
# # 接口调用秘钥(用于SSO模式三的单点注销功能) |
|
||||
secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor |
|
||||
token-name: EL-ADMIN-TOEKN |
|
||||
# # ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明) |
|
||||
# |
|
||||
spring: |
|
||||
#配置 Jpa |
|
||||
jpa: |
|
||||
hibernate: |
|
||||
ddl-auto: none |
|
||||
open-in-view: true |
|
||||
properties: |
|
||||
hibernate: |
|
||||
dialect: org.hibernate.dialect.MySQL5InnoDBDialect |
|
||||
enable_lazy_load_no_trans: true |
|
||||
# 数据源 |
|
||||
datasource: |
|
||||
druid: |
|
||||
db-type: com.alibaba.druid.pool.DruidDataSource |
|
||||
driverClassName: com.mysql.cj.jdbc.Driver |
|
||||
# url: jdbc:log4jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:whxr_test}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true |
|
||||
url: jdbc:mysql://${DB_HOST:47.111.78.178}:${DB_PORT:3306}/${DB_NAME:whxr}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true |
|
||||
username: ${DB_USER:root} |
|
||||
password: ${DB_PWD:P@ssw0rd} |
|
||||
# username: ${DB_USER:root} |
|
||||
# password: ${DB_PWD:root} |
|
||||
# 初始连接数 |
|
||||
initial-size: 5 |
|
||||
# 最小连接数 |
|
||||
min-idle: 15 |
|
||||
# 最大连接数 |
|
||||
max-active: 30 |
|
||||
# 是否自动回收超时连接 |
|
||||
remove-abandoned: true |
|
||||
# 超时时间(以秒数为单位) |
|
||||
remove-abandoned-timeout: 180 |
|
||||
# 获取连接超时时间 |
|
||||
max-wait: 300 |
|
||||
# 连接有效性检测时间 |
|
||||
time-between-eviction-runs-millis: 60000 |
|
||||
# 连接在池中最小生存的时间 |
|
||||
min-evictable-idle-time-millis: 300000 |
|
||||
# 连接在池中最大生存的时间 |
|
||||
max-evictable-idle-time-millis: 900000 |
|
||||
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 |
|
||||
test-while-idle: true |
|
||||
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 |
|
||||
test-on-borrow: true |
|
||||
# 是否在归还到池中前进行检验 |
|
||||
test-on-return: false |
|
||||
# 检测连接是否有效 |
|
||||
validation-query: select 1 |
|
||||
# 配置监控统计 |
|
||||
# webStatFilter: |
|
||||
# enabled: true |
|
||||
# stat-view-servlet: |
|
||||
# enabled: true |
|
||||
# url-pattern: /druid/* |
|
||||
# reset-enable: false |
|
||||
# filter: |
|
||||
# stat: |
|
||||
# enabled: true |
|
||||
# # 记录慢SQL |
|
||||
# log-slow-sql: true |
|
||||
# slow-sql-millis: 1000 |
|
||||
# merge-sql: true |
|
||||
# wall: |
|
||||
# config: |
|
||||
# multi-statement-allow: true |
|
||||
|
|
||||
# Redis配置 (SSO模式一和模式二使用Redis来同步会话) |
|
||||
redis: |
|
||||
# Redis数据库索引(默认为0) |
|
||||
database: 1 |
|
||||
# Redis服务器地址 |
|
||||
host: 47.96.133.178 |
|
||||
# Redis服务器连接端口 |
|
||||
port: 6479 |
|
||||
# Redis服务器连接密码(默认为空) |
|
||||
password: 942464Yy |
|
||||
# 连接超时时间 |
|
||||
timeout: 10s |
|
||||
lettuce: |
|
||||
pool: |
|
||||
# 连接池最大连接数 |
|
||||
max-active: 200 |
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制) |
|
||||
max-wait: -1ms |
|
||||
# 连接池中的最大空闲连接 |
|
||||
max-idle: 10 |
|
||||
# 连接池中的最小空闲连接 |
|
||||
min-idle: 0 |
|
||||
|
|
||||
forest: |
|
||||
# 关闭 forest 请求日志打印 |
|
||||
log-enabled: false |
|
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,8 @@ |
|||||
|
CREATE TABLE `t_javastack` ( |
||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', |
||||
|
`name` varchar(20) NOT NULL COMMENT '姓名', |
||||
|
`age` int(5) DEFAULT NULL COMMENT '年龄', |
||||
|
PRIMARY KEY (`id`) |
||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
||||
|
|
||||
|
|
@ -0,0 +1,8 @@ |
|||||
|
CREATE TABLE `t_javastack` ( |
||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', |
||||
|
`name` varchar(20) NOT NULL COMMENT '姓名', |
||||
|
`age` int(5) DEFAULT NULL COMMENT '年龄', |
||||
|
PRIMARY KEY (`id`) |
||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
||||
|
|
||||
|
|
@ -0,0 +1,8 @@ |
|||||
|
CREATE TABLE `t2_javastack` ( |
||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', |
||||
|
`name` varchar(20) NOT NULL COMMENT '姓名', |
||||
|
`age` int(5) DEFAULT NULL COMMENT '年龄', |
||||
|
PRIMARY KEY (`id`) |
||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
||||
|
|
||||
|
|
Loading…
Reference in new issue