扩展 Web 容器线程池动态调参、监控. (#68)

pull/87/head
chen.ma 3 years ago
parent 3e0a62b1c1
commit c41a7cd8fd

@ -0,0 +1,46 @@
package cn.hippo4j.common.model;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* Pool base info.
*
* @author chen.ma
* @date 2022/1/22 12:10
*/
@Data
@Accessors(chain = true)
public class PoolBaseInfo {
/**
* coreSize
*/
private Integer coreSize;
/**
* maximumSize
*/
private Integer maximumSize;
/**
* queueType
*/
private String queueType;
/**
* queueCapacity
*/
private Integer queueCapacity;
/**
* rejectedName
*/
private String rejectedName;
/**
* keepAliveTime
*/
private Long keepAliveTime;
}

@ -13,7 +13,7 @@ import java.io.Serializable;
*/ */
@Getter @Getter
@Setter @Setter
public class PoolRunStateInfo implements Serializable { public class PoolRunStateInfo extends PoolBaseInfo implements Serializable {
/** /**
* currentLoad * currentLoad
@ -30,21 +30,11 @@ public class PoolRunStateInfo implements Serializable {
*/ */
private String tpId; private String tpId;
/**
* coreSize
*/
private Integer coreSize;
/** /**
* activeCount * activeCount
*/ */
private Integer activeCount; private Integer activeCount;
/**
* maximumSize
*/
private Integer maximumSize;
/** /**
* poolSize * poolSize
*/ */
@ -60,16 +50,6 @@ public class PoolRunStateInfo implements Serializable {
*/ */
private Integer largestPoolSize; private Integer largestPoolSize;
/**
* queueType
*/
private String queueType;
/**
* queueCapacity
*/
private Integer queueCapacity;
/** /**
* queueSize * queueSize
*/ */
@ -115,9 +95,4 @@ public class PoolRunStateInfo implements Serializable {
*/ */
private Long timestamp; private Long timestamp;
/**
* rejectedName
*/
private String rejectedName;
} }

@ -62,6 +62,18 @@ public class ThreadPoolController {
return Results.success(); return Results.success();
} }
@DeleteMapping("/delete")
public Result deletePool(@RequestBody ThreadPoolDelReqDTO reqDTO) {
threadPoolService.deletePool(reqDTO);
return Results.success();
}
@PostMapping("/alarm/enable/{id}/{isAlarm}")
public Result alarmEnable(@PathVariable("id") String id, @PathVariable("isAlarm") Integer isAlarm) {
threadPoolService.alarmEnable(id, isAlarm);
return Results.success();
}
@GetMapping("/list/instance/{itemId}/{tpId}") @GetMapping("/list/instance/{itemId}/{tpId}")
public Result<List<ThreadPoolInstanceInfo>> listInstance(@PathVariable("itemId") String itemId, @PathVariable("tpId") String tpId) { public Result<List<ThreadPoolInstanceInfo>> listInstance(@PathVariable("itemId") String itemId, @PathVariable("tpId") String tpId) {
List<Lease<InstanceInfo>> leases = baseInstanceRegistry.listInstance(itemId); List<Lease<InstanceInfo>> leases = baseInstanceRegistry.listInstance(itemId);
@ -97,16 +109,26 @@ public class ThreadPoolController {
return Results.success(returnThreadPool); return Results.success(returnThreadPool);
} }
@DeleteMapping("/delete") @GetMapping("/list/client/instance/{itemId}")
public Result deletePool(@RequestBody ThreadPoolDelReqDTO reqDTO) { public Result listClientInstance(@PathVariable("itemId") String itemId) {
threadPoolService.deletePool(reqDTO); List<Lease<InstanceInfo>> leases = baseInstanceRegistry.listInstance(itemId);
return Results.success(); Lease<InstanceInfo> first = CollUtil.getFirst(leases);
} if (first == null) {
return Results.success(Lists.newArrayList());
}
@PostMapping("/alarm/enable/{id}/{isAlarm}") List<ThreadPoolInstanceInfo> returnThreadPool = Lists.newArrayList();
public Result alarmEnable(@PathVariable("id") String id, @PathVariable("isAlarm") Integer isAlarm) { leases.forEach(each -> {
threadPoolService.alarmEnable(id, isAlarm); InstanceInfo holder = each.getHolder();
return Results.success(); ThreadPoolInstanceInfo threadPoolInstanceInfo = new ThreadPoolInstanceInfo();
threadPoolInstanceInfo.setActive(holder.getActive());
threadPoolInstanceInfo.setClientAddress(holder.getCallBackUrl());
threadPoolInstanceInfo.setIdentify(holder.getIdentify());
returnThreadPool.add(threadPoolInstanceInfo);
});
return Results.success(returnThreadPool);
} }
} }

@ -47,13 +47,14 @@ public class DiscoveryConfig {
String instanceId = getDefaultInstanceId(environment, hippo4JInetUtils); String instanceId = getDefaultInstanceId(environment, hippo4JInetUtils);
instanceId = StrBuilder.create().append(instanceId).append(":").append(CLIENT_IDENTIFICATION_VALUE).toString(); instanceId = StrBuilder.create().append(instanceId).append(":").append(CLIENT_IDENTIFICATION_VALUE).toString();
String contextPath = environment.getProperty("server.servlet.context-path", "");
instanceInfo.setInstanceId(instanceId) instanceInfo.setInstanceId(instanceId)
.setIpApplicationName(getIpApplicationName(environment, hippo4JInetUtils)) .setIpApplicationName(getIpApplicationName(environment, hippo4JInetUtils))
.setHostName(InetAddress.getLocalHost().getHostAddress()) .setHostName(InetAddress.getLocalHost().getHostAddress())
.setGroupKey(itemId + GROUP_KEY_DELIMITER + namespace) .setGroupKey(itemId + GROUP_KEY_DELIMITER + namespace)
.setAppName(applicationName) .setAppName(applicationName)
.setPort(port) .setPort(port)
.setClientBasePath(environment.getProperty("server.servlet.context-path")) .setClientBasePath(contextPath)
.setGroupKey(ContentUtil.getGroupKey(itemId, namespace)); .setGroupKey(ContentUtil.getGroupKey(itemId, namespace));
String callBackUrl = new StringBuilder().append(instanceInfo.getHostName()).append(":") String callBackUrl = new StringBuilder().append(instanceInfo.getHostName()).append(":")

@ -155,9 +155,8 @@ public class DynamicThreadPoolAutoConfiguration {
@Bean @Bean
public WebThreadPoolController webThreadPoolController(WebThreadPoolHandlerChoose webThreadPoolServiceChoose, public WebThreadPoolController webThreadPoolController(WebThreadPoolHandlerChoose webThreadPoolServiceChoose,
ThreadDetailState threadDetailState,
WebThreadPoolRunStateHandler webThreadPoolRunStateHandler) { WebThreadPoolRunStateHandler webThreadPoolRunStateHandler) {
return new WebThreadPoolController(webThreadPoolServiceChoose, threadDetailState, webThreadPoolRunStateHandler); return new WebThreadPoolController(webThreadPoolServiceChoose, webThreadPoolRunStateHandler);
} }
} }

@ -1,6 +1,6 @@
package cn.hippo4j.starter.controller; package cn.hippo4j.starter.controller;
import cn.hippo4j.common.api.ThreadDetailState; import cn.hippo4j.common.model.PoolBaseInfo;
import cn.hippo4j.common.model.PoolParameterInfo; import cn.hippo4j.common.model.PoolParameterInfo;
import cn.hippo4j.common.model.PoolRunStateInfo; import cn.hippo4j.common.model.PoolRunStateInfo;
import cn.hippo4j.common.web.base.Result; import cn.hippo4j.common.web.base.Result;
@ -26,10 +26,16 @@ public class WebThreadPoolController {
private final WebThreadPoolHandlerChoose webThreadPoolServiceChoose; private final WebThreadPoolHandlerChoose webThreadPoolServiceChoose;
private final ThreadDetailState threadDetailState;
private final WebThreadPoolRunStateHandler webThreadPoolRunStateHandler; private final WebThreadPoolRunStateHandler webThreadPoolRunStateHandler;
@GetMapping("/web/base/info")
public Result<PoolBaseInfo> getPoolBaseState() {
WebThreadPoolService webThreadPoolService = webThreadPoolServiceChoose.choose();
Executor webThreadPool = webThreadPoolService.getWebThreadPool();
PoolBaseInfo poolBaseInfo = webThreadPoolRunStateHandler.simpleInfo(webThreadPool);
return Results.success(poolBaseInfo);
}
@GetMapping("/web/run/state") @GetMapping("/web/run/state")
public Result<PoolRunStateInfo> getPoolRunState() { public Result<PoolRunStateInfo> getPoolRunState() {
WebThreadPoolService webThreadPoolService = webThreadPoolServiceChoose.choose(); WebThreadPoolService webThreadPoolService = webThreadPoolServiceChoose.choose();

@ -1,5 +1,6 @@
package cn.hippo4j.starter.handler; package cn.hippo4j.starter.handler;
import cn.hippo4j.common.model.PoolBaseInfo;
import cn.hippo4j.common.model.PoolRunStateInfo; import cn.hippo4j.common.model.PoolRunStateInfo;
import cn.hippo4j.starter.core.DynamicThreadPoolExecutor; import cn.hippo4j.starter.core.DynamicThreadPoolExecutor;
import cn.hippo4j.starter.core.GlobalThreadPoolManage; import cn.hippo4j.starter.core.GlobalThreadPoolManage;
@ -20,6 +21,16 @@ import java.util.concurrent.ThreadPoolExecutor;
*/ */
public abstract class AbstractThreadPoolRuntime { public abstract class AbstractThreadPoolRuntime {
/**
* Simple info.
*
* @param executor
* @return
*/
protected PoolBaseInfo simpleInfo(Executor executor) {
return null;
}
/** /**
* Supplement. * Supplement.
* *

@ -48,11 +48,22 @@ public class TomcatWebThreadPoolHandler extends AbstractWebThreadPoolService {
@Override @Override
public void updateWebThreadPool(PoolParameterInfo poolParameterInfo) { public void updateWebThreadPool(PoolParameterInfo poolParameterInfo) {
ThreadPoolExecutor tomcatExecutor = (ThreadPoolExecutor) executor;
try { try {
ThreadPoolExecutor tomcatExecutor = (ThreadPoolExecutor) executor;
int originalCoreSize = tomcatExecutor.getCorePoolSize();
int originalMaximumPoolSize = tomcatExecutor.getMaximumPoolSize();
long originalKeepAliveTime = tomcatExecutor.getKeepAliveTime(TimeUnit.SECONDS);
tomcatExecutor.setCorePoolSize(poolParameterInfo.getCoreSize()); tomcatExecutor.setCorePoolSize(poolParameterInfo.getCoreSize());
tomcatExecutor.setMaximumPoolSize(poolParameterInfo.getMaxSize()); tomcatExecutor.setMaximumPoolSize(poolParameterInfo.getMaxSize());
tomcatExecutor.setKeepAliveTime(poolParameterInfo.getKeepAliveTime(), TimeUnit.SECONDS); tomcatExecutor.setKeepAliveTime(poolParameterInfo.getKeepAliveTime(), TimeUnit.SECONDS);
log.info(
"🔥 Changed web thread pool. coreSize :: [{}], maxSize :: [{}], keepAliveTime :: [{}]",
String.format("%s => %s", originalCoreSize, poolParameterInfo.getCoreSize()),
String.format("%s => %s", originalMaximumPoolSize, poolParameterInfo.getMaxSize()),
String.format("%s => %s", originalKeepAliveTime, poolParameterInfo.getKeepAliveTime())
);
} catch (Exception ex) { } catch (Exception ex) {
log.error("Failed to modify the Tomcat thread pool parameter.", ex); log.error("Failed to modify the Tomcat thread pool parameter.", ex);
} }

@ -1,7 +1,13 @@
package cn.hippo4j.starter.handler.web; package cn.hippo4j.starter.handler.web;
import cn.hippo4j.common.model.PoolBaseInfo;
import cn.hippo4j.common.model.PoolRunStateInfo; import cn.hippo4j.common.model.PoolRunStateInfo;
import cn.hippo4j.starter.handler.AbstractThreadPoolRuntime; import cn.hippo4j.starter.handler.AbstractThreadPoolRuntime;
import cn.hippo4j.starter.toolkit.ByteConvertUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.system.RuntimeInfo;
import java.util.concurrent.*;
/** /**
* Web thread pool run state handler. * Web thread pool run state handler.
@ -12,8 +18,48 @@ import cn.hippo4j.starter.handler.AbstractThreadPoolRuntime;
public class WebThreadPoolRunStateHandler extends AbstractThreadPoolRuntime { public class WebThreadPoolRunStateHandler extends AbstractThreadPoolRuntime {
@Override @Override
protected PoolRunStateInfo supplement(PoolRunStateInfo basePoolRunStateInfo) { public PoolBaseInfo simpleInfo(Executor executor) {
return basePoolRunStateInfo; PoolBaseInfo poolBaseInfo = new PoolBaseInfo();
if (executor != null && executor instanceof ThreadPoolExecutor) {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
int corePoolSize = threadPoolExecutor.getCorePoolSize();
int maximumPoolSize = threadPoolExecutor.getMaximumPoolSize();
RejectedExecutionHandler rejectedExecutionHandler = threadPoolExecutor.getRejectedExecutionHandler();
long keepAliveTime = threadPoolExecutor.getKeepAliveTime(TimeUnit.SECONDS);
BlockingQueue<Runnable> queue = threadPoolExecutor.getQueue();
int queueSize = queue.size();
int remainingCapacity = queue.remainingCapacity();
int queueCapacity = queueSize + remainingCapacity;
poolBaseInfo.setCoreSize(corePoolSize);
poolBaseInfo.setMaximumSize(maximumPoolSize);
poolBaseInfo.setKeepAliveTime(keepAliveTime);
poolBaseInfo.setQueueType(queue.getClass().getSimpleName());
poolBaseInfo.setQueueCapacity(queueCapacity);
poolBaseInfo.setRejectedName(rejectedExecutionHandler.getClass().getSimpleName());
}
return poolBaseInfo;
}
@Override
protected PoolRunStateInfo supplement(PoolRunStateInfo poolRunStateInfo) {
// 内存占比: 使用内存 / 最大内存
RuntimeInfo runtimeInfo = new RuntimeInfo();
String memoryProportion = StrUtil.builder(
"已分配: ",
ByteConvertUtil.getPrintSize(runtimeInfo.getTotalMemory()),
" / 最大可用: ",
ByteConvertUtil.getPrintSize(runtimeInfo.getMaxMemory())
).toString();
poolRunStateInfo.setCurrentLoad(poolRunStateInfo.getCurrentLoad() + "%");
poolRunStateInfo.setPeakLoad(poolRunStateInfo.getPeakLoad() + "%");
poolRunStateInfo.setMemoryProportion(memoryProportion);
poolRunStateInfo.setFreeMemory(ByteConvertUtil.getPrintSize(runtimeInfo.getFreeMemory()));
return poolRunStateInfo;
} }
} }

Loading…
Cancel
Save