This commit is contained in:
ialbert 2025-11-25 15:44:08 +03:00
parent c65d88f645
commit 015c7ca24b
5 changed files with 25 additions and 8 deletions

View file

@ -6,6 +6,7 @@ import org.springframework.boot.context.properties.bind.DefaultValue;
public record PipelineSettings( public record PipelineSettings(
@DefaultValue("5000") Integer subjectBatchSize, @DefaultValue("5000") Integer subjectBatchSize,
@DefaultValue("3") Integer saveSubjectStageConcurrency,
@DefaultValue("15") Integer nameEnricherStageConcurrency, @DefaultValue("15") Integer nameEnricherStageConcurrency,
@DefaultValue("10") Integer idEnricherStageConcurrency, @DefaultValue("10") Integer idEnricherStageConcurrency,
@DefaultValue("5") Integer errorAttemptCount, @DefaultValue("5") Integer errorAttemptCount,

View file

@ -79,6 +79,7 @@ public class PipelinePackageManager {
this.fidNameEnricher = fidNameEnricher; this.fidNameEnricher = fidNameEnricher;
this.creditTrackerSettings = creditTrackerSettings; this.creditTrackerSettings = creditTrackerSettings;
this.semaphore = new Semaphore(creditTrackerSettings.getPipeline().parallelRequests()); this.semaphore = new Semaphore(creditTrackerSettings.getPipeline().parallelRequests());
log.info("pipeline settings: {}", creditTrackerSettings.getPipeline());
this.pipelineBackoff = pipelineBackoff; this.pipelineBackoff = pipelineBackoff;
} }
@ -87,6 +88,7 @@ public class PipelinePackageManager {
throw new RuntimeException("Too many concurrent requests"); throw new RuntimeException("Too many concurrent requests");
} }
log.info("throttler permits after acquire: {}", semaphore.availablePermits()); log.info("throttler permits after acquire: {}", semaphore.availablePermits());
long startTime = System.currentTimeMillis();
try { try {
Pipeline pipeline = PipeLineBuilderV2.first(saveSubjectQueueFactory.getObject(), idEnricherQueueFactory.getObject()) Pipeline pipeline = PipeLineBuilderV2.first(saveSubjectQueueFactory.getObject(), idEnricherQueueFactory.getObject())
.handler(saveSubjectHandler) .handler(saveSubjectHandler)
@ -110,6 +112,8 @@ public class PipelinePackageManager {
.orTimeout(creditTrackerSettings.getPipeline().globalTimeout().toMillis(), TimeUnit.MILLISECONDS) .orTimeout(creditTrackerSettings.getPipeline().globalTimeout().toMillis(), TimeUnit.MILLISECONDS)
.whenComplete((v, e) -> { .whenComplete((v, e) -> {
try { try {
long finishTime = System.currentTimeMillis();
log.info("pipeline time passed: {} ms", finishTime - startTime);
if (e instanceof XmlMergeCoordinator.PipelineTerminatorException) { if (e instanceof XmlMergeCoordinator.PipelineTerminatorException) {
log.info("when complete: terminator was interrupted."); log.info("when complete: terminator was interrupted.");
return; return;

View file

@ -5,7 +5,7 @@ import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -13,8 +13,8 @@ import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import ru.nbch.credit_tracker.model.StagePayload; import ru.nbch.credit_tracker.model.StagePayload;
import ru.nbch.credit_tracker.utils.TaskTimer;
import ru.nbch.credit_tracker.utils.LogUtil; import ru.nbch.credit_tracker.utils.LogUtil;
import ru.nbch.credit_tracker.utils.TaskTimer;
@Slf4j @Slf4j
public class Stage<X extends StagePayload, Z extends StagePayload> implements Runnable { public class Stage<X extends StagePayload, Z extends StagePayload> implements Runnable {
@ -42,10 +42,11 @@ public class Stage<X extends StagePayload, Z extends StagePayload> implements Ru
this.out = out; this.out = out;
this.dispatcherName = dispatcher.getClass().getSimpleName(); this.dispatcherName = dispatcher.getClass().getSimpleName();
var mdcMap = LogUtil.extractMdcMap(); var mdcMap = LogUtil.extractMdcMap();
BlockingQueue<Runnable> handoffQueue = new SynchronousQueue<>();
this.ioPool = new ThreadPoolExecutor(dispatcher.preferredConcurrency(), this.ioPool = new ThreadPoolExecutor(dispatcher.preferredConcurrency(),
dispatcher.preferredConcurrency(), dispatcher.preferredConcurrency(),
0L, TimeUnit.MINUTES, 0L, TimeUnit.MINUTES,
new LinkedBlockingQueue<>(1), handoffQueue,
r -> { r -> {
Thread t = new Thread(LogUtil.wrap(mdcMap, r)); Thread t = new Thread(LogUtil.wrap(mdcMap, r));
t.setName("pipe-handler-%s-%d".formatted(dispatcherName, t.threadId())); t.setName("pipe-handler-%s-%d".formatted(dispatcherName, t.threadId()));
@ -53,7 +54,13 @@ public class Stage<X extends StagePayload, Z extends StagePayload> implements Ru
}, },
(r, executor) -> { (r, executor) -> {
log.info("stage {}: all threads are working; switch to CallerRunsPolicy", dispatcherName); log.info("stage {}: all threads are working; switch to CallerRunsPolicy", dispatcherName);
callerRunsPolicy.rejectedExecution(r, executor); try {
//блокировать отправителя, пока какойто рабочий поток не возьмёт задачу
handoffQueue.put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// callerRunsPolicy.rejectedExecution(r, executor);
} }
); );
} }
@ -79,7 +86,6 @@ public class Stage<X extends StagePayload, Z extends StagePayload> implements Ru
} }
f.get(); f.get();
} }
log.trace("Stage time stats: {}", stopWatch.info());
dispatcher.handleOnPoison(b); dispatcher.handleOnPoison(b);
putQuiet(out, dispatcher.cookPoison()); putQuiet(out, dispatcher.cookPoison());
log.info("stage {} finished.", dispatcherName); log.info("stage {} finished.", dispatcherName);
@ -97,7 +103,7 @@ public class Stage<X extends StagePayload, Z extends StagePayload> implements Ru
} }
log.info("stage {} task {} started.", dispatcher.getClass().getSimpleName(), finalCounter); log.info("stage {} task {} started.", dispatcher.getClass().getSimpleName(), finalCounter);
Z p; Z p;
try (var m = stopWatch.start(dispatcherName)){ try (var m = stopWatch.start(dispatcherName + "-handler")){
p = dispatcher.handle(b); p = dispatcher.handle(b);
} }
if (Thread.currentThread().isInterrupted()) { if (Thread.currentThread().isInterrupted()) {
@ -159,6 +165,7 @@ public class Stage<X extends StagePayload, Z extends StagePayload> implements Ru
public void close() { public void close() {
log.info("Stage {} is getting shutdown", dispatcher.getClass().getSimpleName()); log.info("Stage {} is getting shutdown", dispatcher.getClass().getSimpleName());
log.trace("Stage time stats: {}", stopWatch.info());
ioPool.shutdownNow(); // прерываем обработчики ioPool.shutdownNow(); // прерываем обработчики
} }

View file

@ -57,7 +57,7 @@ public class SaveSubjectHandler implements Handler<SubjectPayload, SubjectPayloa
@Override @Override
public int preferredConcurrency() { public int preferredConcurrency() {
return 20; return creditTrackerSettings.getPipeline().saveSubjectStageConcurrency();
} }
@Override @Override

View file

@ -21,6 +21,7 @@ import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
import ru.nbch.credit_tracker.model.impl.PartFilePayload; import ru.nbch.credit_tracker.model.impl.PartFilePayload;
import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload; import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload;
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator; import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
import ru.nbch.credit_tracker.utils.TaskTimer;
@Slf4j @Slf4j
public final class XmlMergeCoordinator implements IPipeLineTerminator<PartFilePayload, SignalXmlFilePayload> { public final class XmlMergeCoordinator implements IPipeLineTerminator<PartFilePayload, SignalXmlFilePayload> {
@ -29,6 +30,7 @@ public final class XmlMergeCoordinator implements IPipeLineTerminator<PartFilePa
private Path out; private Path out;
private final CreditTrackerSettings config; private final CreditTrackerSettings config;
private BlockingQueue<PartFilePayload> inQueue; private BlockingQueue<PartFilePayload> inQueue;
private final TaskTimer stopWatch = new TaskTimer();
public XmlMergeCoordinator(CreditTrackerSettings config) { public XmlMergeCoordinator(CreditTrackerSettings config) {
this.config = config; this.config = config;
@ -45,9 +47,12 @@ public final class XmlMergeCoordinator implements IPipeLineTerminator<PartFilePa
if (part.isPoison()) { if (part.isPoison()) {
log.debug("Got poison"); log.debug("Got poison");
done.complete(new SignalXmlFilePayload(out)); done.complete(new SignalXmlFilePayload(out));
log.info("Stage time stats: {}", stopWatch.info());
return; return;
} }
try (var m = stopWatch.start("XmlMergeCoordinator")) {
mergeBatch(part); mergeBatch(part);
}
} catch (InterruptedException ie) { } catch (InterruptedException ie) {
log.info("pipeline terminator was interrupted!"); log.info("pipeline terminator was interrupted!");
done.completeExceptionally(new PipelineTerminatorException()); done.completeExceptionally(new PipelineTerminatorException());