dynamic-tp动态线程池
动态线程池,可以通过nacos配置动态修改线程池参数,官网 以下是dynamic-tp与nacos集成的步骤,更详细配置项可以查看官网
- 引入依赖坐标
<dependency>
<groupId>org.dromara.dynamictp</groupId>
<artifactId>dynamic-tp-spring-cloud-starter-nacos</artifactId>
<version>1.1.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.dromara.dynamictp</groupId>
<artifactId>dynamic-tp-extension-skywalking</artifactId>
<version>1.1.3</version>
</dependency>
- 添加配置项
spring:
dynamic:
tp:
enabled: true # 是否启用 dynamictp,默认true
enabledCollect: true # 是否开启监控指标采集,默认true
collectorTypes: internal_logging # 监控数据采集器类型(logging | micrometer | internal_logging | JMX),默认micrometer
monitorInterval: 5 # 监控时间间隔(报警检测、指标采集),默认5s
executors: # 动态线程池配置,都有默认值,采用默认值的可以不配置该项,减少配置量
- threadPoolName: dtpExecutor1 # 线程池名称,必填
threadPoolAliasName: 测试线程池 # 线程池别名,可选
executorType: common # 线程池类型 common、eager、ordered、scheduled、priority,默认 common
corePoolSize: 6 # 核心线程数,默认1
maximumPoolSize: 8 # 最大线程数,默认cpu核数
queueCapacity: 2000 # 队列容量,默认1024
queueType: VariableLinkedBlockingQueue # 任务队列,查看源码QueueTypeEnum枚举类,默认VariableLinkedBlockingQueue
rejectedHandlerType: CallerRunsPolicy # 拒绝策略,查看RejectedTypeEnum枚举类,默认AbortPolicy
keepAliveTime: 60 # 空闲线程等待超时时间,默认60
threadNamePrefix: test # 线程名前缀,默认dtp
allowCoreThreadTimeOut: false # 是否允许核心线程池超时,默认false
waitForTasksToCompleteOnShutdown: true # 参考spring线程池设计,优雅关闭线程池,默认true
awaitTerminationSeconds: 5 # 优雅关闭线程池时,阻塞等待线程池中任务执行时间,默认3,单位(s)
preStartAllCoreThreads: false # 是否预热所有核心线程,默认false
runTimeout: 200 # 任务执行超时阈值,单位(ms),默认0(不统计)
queueTimeout: 100 # 任务在队列等待超时阈值,单位(ms),默认0(不统计)
taskWrapperNames: ["swTrace"] # 任务包装器名称,继承TaskWrapper接口
notifyEnabled: false # 是否开启报警,默认true
nacos作为配置中心
- 引入依赖坐标
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
- 新增bootstrap.yml
spring:
application:
name: TEST-CONFIG
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
username: root
password: root
file-extension: yaml
extension-configs:
- dataId: ${spring.application.name}.${spring.cloud.nacos.config.file-extension}
group: DEFAULT_GROUP
refresh: true
refresh-enabled: true
---
spring:
profiles: test
cloud:
nacos:
config:
namespace: test
guava-retry重试
- 引入依赖坐标
<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>2.0.0</version>
</dependency>
- 创建重试器
private static final Retryer<TestDTO> retryer;
static {
retryer = RetryerBuilder.<TestDTO>newBuilder()
// 重试条件
.retryIfException() // 抛出异常时重试
.retryIfResult(Predicates.isNull()) // 返回结果为null时重试
// 等待策略:每次请求间隔3s
.withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))
// 停止策略:尝试请求5次
.withStopStrategy(StopStrategies.stopAfterAttempt(5))
.build();
}
- 使用重试
Callable<TestDTO> callable = new Callable<TestDTO>() {
int times = 0;
@Override
public TestDTO call() throws Exception {
times++;
log.info("第{}次请求", times);
try {
// TODO 具体逻辑
return new TestDTO();
} catch (Exception e) {
log.error("请求失败", e);
return null;
}
}
};
try {
retryer.call(callable);
} catch (Exception e) {
log.error("重试请求异常", e);
}
hystrix和ribben超时时间
# ribbon的超时时间
ribbon:
ReadTimeout: 9000
ConnectTimeout: 9000
# 配置需要立即加载的其他服务(饿加载)
eager-load:
enabled: true
clients: TEST-JOB
# hystrix的超时时间
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 9000
threadpool:
TEST-CONFIG:
coreSize: 10 # 核心线程数 默认10
maximumSize: 20 # 最大线程数 默认10
maxQueueSize: 20 # 队列最大长度 默认-1
allowMaximumSizeToDivergeFromCoreSize: true # 允许最大线程数超过核心线程数 默认false
queueSizeRejectionThreshold: 20 # 队列大小拒绝阈值 默认5
curl
curl -H 'Content-Type: application/json' -X POST -o --location 'https://www.xxx.com' -d '{"aooliType": "0"}'
-H: 请求头
-X: 请求方式
-d: 请求体
-o --location: 如果有些https地址不安全可以添加该参数跳过验证
curl -o /dev/null -s -w "total time: %{time_total} seconds\n" 命令中加入这些参数可以测试curl调用url用时多少秒
traceId和tid
作为分布式链路追踪技术中,一般使用有spring-cloud-sleuth(zipkin),skywalking等等。traceId是sleuth中的概念,而在skywalking中类似概念的是tid,它们都表示一个链路的唯一id,可以通过这个id将一次微服务调用串联起来
spring-cloud-sleuth
- 引入依赖坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
- 修改日志文件(logback.spring.xml)
<!-- 输出日志到文件 -->
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${app.log_dir}/log_error.log</file>
<!--日志文件输出格式 X-B3-TraceId X-B3-SpanId X-B3-ParentSpanId是sleuth中固定的名词-->
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [${appName},%x{X-B3-TraceId},%x{X-B3-SpanId},%x{X-B3-ParentSpanId}] --[%thread] %logger %msg</pattern>
</layout>
<!-- 此处设置字符集 -->
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器指定拆分策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--按照时间拆分文件名 如果以.gz或.zip结尾可以压缩-->
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--按照文件大小拆分-->
<maxFileSize>100MB</maxFileSize>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
- 以上配置代码中输出log即可,但是在多线程中需要将TraceId传过去
@Autowired
private Tracer tracer;
public void test(String[] args) {
Span span = tracer.currentSpan();
CompletableFuture.supplyAsync(() -> {
tracer.withSpanInScope(span);
log.info("业务逻辑开始");
// TODO 业务逻辑
return new TestDTO();
}).exceptionally(throwable -> {
log.error("请求失败", throwable);
return null;
});
}
skywalking
- 引入依赖坐标
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.11.0</version>
</dependency>
- 修改日志文件(logback.spring.xml)
<!-- 输出日志到文件 -->
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${app.log_dir}/log_error.log</file>
<!--日志文件输出格式 tid是skywalking中固定的名词-->
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%tid] --[%thread] %logger %msg</pattern>
</layout>
<!-- 此处设置字符集 -->
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器指定拆分策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--按照时间拆分文件名 如果以.gz或.zip结尾可以压缩-->
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--按照文件大小拆分-->
<maxFileSize>100MB</maxFileSize>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
</appender>
- 以上配置代码中输出log即可,但是在多线程中需要处理下
CompletableFuture.supplyAsync(SupplierWrapper.of(() -> {
log.info("业务逻辑开始");
// TODO 业务逻辑
return new TestDTO();
})).exceptionally(FunctionWrapper.of(throwable -> {
log.error("请求失败", throwable);
return null;
}));
// 如果多线程不需要返回值
CompletableFuture.runAsync(RunnableWrapper.of(() -> {
log.info("业务逻辑开始");
// TODO 业务逻辑
}));
skywalking是在jar启动时通过javaagent参数执行的
-javaagent:/home/appadmin/skywalking_agent/skywalking-agent.jar -Dskywalking.agent.service_name=TEST_CONFIG -Dskywalking.agent.instance_name=TEST_CONFIG_${ip}_${PORT}
指定jar包路径以及服务名和实例名
jasypt加密
整合SpringBoot项目
- 引入依赖坐标
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
-
启动参数添加jasypt密钥
本地启动:Idea Program arguments添加参数--jasypt.encryptor.password=密钥
服务器启动:SpringBoot启动参数添加--jasypt.encryptor.password=密钥
-
通过代码生成密文,将生成的密文替换为原本的密码,格式为
ENC(密文)