All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.neko233.toolchain.actor.ActorWorkerManager Maven / Gradle / Ivy

package com.neko233.toolchain.actor;


import com.neko233.toolchain.actor.strategy.ActorIdStrategy;
import com.neko233.toolchain.actor.strategy.ActorIdStrategyConstant;
import com.neko233.toolchain.actor.strategy.ActorIdStrategyFactory;
import com.neko233.toolchain.common.lifecycle.GlobalLifeCycle;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;


/**
 * Actor Worker 管理器
 * {@link ActorApi 使用对象, 必须实现该 API}
 */
@Slf4j
public class ActorWorkerManager implements GlobalLifeCycle {


    public static final int Default_MQ_SIZE_1W = 10000;
    public static final int DEFAULT_WORKER_NUMBER = Runtime.getRuntime().availableProcessors() * 2;
    private final String name;
    private Worker[] workers;
    private final int workerNum;
    private final int workerMqSize;
    private final long shutdownTimeoutMs; // 等待关闭的超时时间,单位毫秒

    // actorId 生成策略
    private ActorIdStrategy strategy = ActorIdStrategyFactory.choose(ActorIdStrategyConstant.LOAD_BALANCE);

    public ActorWorkerManager() {
        this("Default-WorkerCenter", DEFAULT_WORKER_NUMBER, 1000);
    }

    public ActorWorkerManager(String workerCenterName, Integer workerNumber, Integer workerMqSize) {
        this.name = workerCenterName;
        this.workerNum = Optional.ofNullable(workerNumber).orElse(DEFAULT_WORKER_NUMBER);
        this.workerMqSize = Optional.ofNullable(workerMqSize).orElse(Default_MQ_SIZE_1W);
        this.shutdownTimeoutMs = 20_000L;
    }

    public synchronized void changeActorIdStrategy(ActorIdStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 随机一个 worker 执行都可以
     */
    public void addRandomTask(WorkerTask workerTask) throws ActorBindException {
        addActorTask(System.currentTimeMillis(), workerTask);
    }

    /**
     * 移除某个东西对 Thread 的使用, 用来进行统计
     */
    public void removeActorUse(long toShardingId) {
        if (strategy == null) {
            log.error("you forget to config your ActorIdStrategy!");
            return;
        }
        int actorId = strategy.getActorId(toShardingId, workers.length);
        if (actorId < 0) {
            log.error("your task not work because actorId < 0. actorId = {}", actorId);
            return;
        }

        strategy.minusUse(actorId);
    }

    /**
     * 固定 User 对应的 Thread
     *
     * @param toShardingId 分片id. 一般是 userId
     * @param workerTask   任务
     * @return -1 error / actorId >= 0
     */
    public int addActorTask(long toShardingId, WorkerTask workerTask) {

        if (strategy == null) {
            log.error("you forget to config your ActorIdStrategy!");
            return -1;
        }
        int actorId = strategy.getActorId(toShardingId, workers.length);
        if (actorId < 0) {
            log.error("your task not work because actorId < 0. actorId = {}", actorId);
            return -1;
        }
        strategy.increaseUse(actorId);

        Worker worker = null;
        try {
            worker = workers[actorId];
        } catch (Exception e) {
            log.error("get worker error by actorId = {}", actorId);
            return -1;
        }

        worker.addTask(workerTask);
        return actorId;
    }


    public void addActorTaskByHashCode(Object shardingObject, WorkerTask workerTask) throws ActorBindException {
        if (shardingObject == null) {
            return;
        }
        int hashCode = shardingObject.hashCode();
        addActorTask((long) hashCode, workerTask);
    }

    @Override
    public void init() throws Throwable {
        this.workers = new Worker[workerNum];
        for (int index = 0; index < workers.length; index++) {
            this.workers[index] = new Worker(name, index, workerMqSize);
        }

        log.info("[WorkerCenter] start workers. workerCenter Name = {}, worker total size = {}", name, workers.length);
        for (Worker worker : workers) {
            worker.start();
        }
    }

    @Override
    public void create() throws Throwable {

    }

    @Override
    public void destroy() {
        log.info("[WorkerCenter] stop workers. workerCenter Name = {}, worker total size = {}", name, workers.length);
        // 先全部停止运行的状态,再关闭
        for (Worker worker : workers) {
            worker.sendStopSignal();
        }
        long globalStopNs = System.currentTimeMillis();
        for (Worker worker : workers) {
            worker.waitShutdown(globalStopNs, shutdownTimeoutMs);
        }
    }

    @Override
    public void shutdown() {

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy