• Stars
    star
    441
  • Rank 95,396 (Top 2 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created about 2 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Gobrs-Async (异步任务 编排框架) 是一款功能强大、配置灵活、带有全链路异常回调、内存优化、异常状态管理于一身的高性能异步编排框架。为企业提供在复杂应用场景下动态任务编排的能力。 针对于复杂场景下,异步线程复杂性、任务依赖性、异常状态难控制性; Gobrs-Async 为此而生。

资源索引

Gobrs-Async 介绍

Gobrs-Async 是一款功能强大、配置灵活、带有全链路异常回调、内存优化、异常状态管理于一身的高性能多线程并发编程和动态编排框架。为企业提供在复杂应用场景下动态任务编排的能力。 针对于复杂场景下,异步线程复杂性、任务依赖性、异常状态难控制性; Gobrs-Async 为此而生。

解决什么问题

在开发复杂中台业务过程中,难免会遇到调用各种中台业务数据, 而且会出现复杂的中台数据依赖关系,在这种情况下。代码的复杂程度就会增加。 如下图所示: 1.1

最新版本

<dependency>
    <groupId>io.github.memorydoc</groupId>
    <artifactId>gobrs-async-starter</artifactId>
    <version>1.2.9-RELEASE</version>
</dependency>

快速上手

克隆 Gobrs-Async 源代码

启动 Gobrs-Async-Example 模块下 GobrsAsyncExampleApplication 应用类

通过接口修改线程池中的配置。HTTP GET 路径:http://localhost:8888/gobrs/testGobrs,查看Idea 控制台 打印结果如下:

EService Begin
AService Begin
AService Finish
BService Begin
BService Finish
FService Begin
EService Finish
CService Begin
CService Finish
FService Finish
GService Begin
GService Finish
HService Begin
HService Finish
2022-11-27 19:08:51.080  INFO 61949 --- [nio-8888-exec-1] com.gobrs.async.core.TaskLoader          : 【ProcessTrace】Total cost: 2536ms | traceId = 11702850586978176 | 【task】AService cost :302ms【state】:success; ->【task】BService cost :0ms【state】:success; ->【task】EService cost :602ms【state】:success; ->【task】CService cost :305ms【state】:success; ->【task】FService cost :2006ms【state】:success; ->【task】GService cost :105ms【state】:success; ->【task】HService cost :102ms【state】:success;
2551

执行过程

从日志中可以看出整个流程的执行过程

【ProcessTrace】Total cost: 2536ms | traceId = 11702850586978176 | 【task】AService cost :302ms【state】:success; ->【task】BService cost :0ms【state】:success; ->【task】EService cost :602ms【state】:success; ->【task】CService cost :305ms【state】:success; ->【task】FService cost :2006ms【state】:success; ->【task】GService cost :105ms【state】:success; ->【task】HService cost :102ms【state】:success;
  • Total cost: 任务流程总耗时
  • traceId: 任务流程链路id
  • cost: 单个任务执行时间

配置文件

server:
  port: 8888 # 端口: 8888
gobrs:
  async:
    config:
      rules:
        # 规则 是数组类型的 多组规则
        - name: "general"
          content: "AService->BService->FService->GService->HService;EService->CService;AService"
          task-interrupt: false # 局部异常是否打断主流程 默认false
          transaction: false

关闭Gobrs-Async

server:
  port: 8888 # 端口: 8080
gobrs:
async:
  enable: false # 关闭编排引擎
  rules:
    # 支持多命名空间
    - name: "ruleName" # 规则名称
      content: "AService->BService,CService,FService; BService->FService,GService;"
    - name: "azh"
      content: "AService->BService,CService,FService; BService->FService,GService;"
  task-interrupt: false #局部异常是否打断主流程

完整配置示例

gobrs:
  async:
    config:
      rules:
        # 规则 是数组类型的 多组规则
        - name: "general"
          content: "AService->BService->FService->GService->HService;EService->CService;AService"
          task-interrupt: true # 局部异常是否打断主流程 默认false
          transaction: true
        - name: "anyConditionGeneral"
          content: "AServiceCondition,BServiceCondition,CServiceCondition->DServiceCondition"
          logConfig:
            costLogabled: false # 开启任务耗时打印 log日志级别需要为 error 默认true
            errLogabled: true # 开启任务异常打印 默认true
        #  AServiceCondition 、BServiceCondition、CServiceCondition任务谁返回true 谁有资格继续往下执行
        - name: "anyConditionRule"
          content: "AServiceCondition,BServiceCondition,CServiceCondition->DServiceCondition:anyCondition"

        - name: "anyConditionRuleAppend"
          content: "AServiceCondition,BServiceCondition,CServiceCondition->DServiceCondition:anyCondition->EServiceCondition"

        # 官方场景一 https://async.sizegang.cn/pages/2f844b/#%E5%9C%BA%E6%99%AF%E4%B8%80
        - name: "caseOne"
          content: "caseOneTaskA->caseOneTaskB,caseOneTaskC,caseOneTaskD"

        # 官方场景二 https://async.sizegang.cn/pages/2f844b/#%E5%9C%BA%E6%99%AF%E4%BA%8C
        - name: "caseTwo"
          content: "caseTwoTaskA->caseTwoTaskB->caseTwoTaskC,caseTwoTaskD"
        # 官方场景三 https://async.sizegang.cn/pages/2f844b/#%E5%9C%BA%E6%99%AF%E4%B8%89
        - name: "caseThree"
          content: "caseThreeTaskA->caseThreeTaskB,caseThreeTaskC,caseFourTaskD->caseThreeTaskG;
                    caseThreeTaskA->caseThreeTaskE,caseThreeTaskF->caseThreeTaskG;"
        # 官方场景四 https://async.sizegang.cn/pages/2f844b/#%E5%9C%BA%E6%99%AF%E5%9B%9B
        - name: "caseFour"
          content: "caseFourTaskA->caseFourTaskB->caseFourTaskC,caseFourTaskD,caseFourTaskE;
                    caseFourTaskA->caseFourTaskH->caseFourTaskI,caseFourTaskJ,caseFourTaskK;"
          logConfig:
            costLogabled: false # 关闭耗时任务打印
        # 官方场景五 https://async.sizegang.cn/pages/2f844b/#%E5%9C%BA%E6%99%AF%E4%BA%94
        - name: "caseFive"
          content: "caseFourTaskA,caseFourTaskB,caseFourTaskC->caseFourTaskD:any:exclusive" # any 任意一个任务(A、B、C)执行完成后 则执行D任务
          # exclusive 避免任务执行浪费 所以 D执行完成之后 会主动 中断 未完成的任务
server:
  port: 9999 # 端口: 8080

配置文件位置

如果开发者配置较多 与 springboot 配置文件放在一起有点冗余的话,可以在 resources/config 目录下创建以下配置文件都是支持的。

  • gobrs.yaml

  • gobrs.yml

  • gobrs.properties

规则组成

规则名称 name

规则对象又两部分组成:

  • 规则名称
  • 规则内容

规则名称(name) 约定规则的唯一标识符: 在任务触发器开发触发任务的时候需要传递。

规则内容 content

规则内容(content) 则是规则引擎解析的核心内容,根据任务执行流程不同,任务规则配置也会不同,但是不会很复杂,详细配置流程分为一下几种场景。

日志配置 logConfig

  • costLogabled 流程日志打印 包括耗时时间,调用链路等
  • errLogabled 任务执行异常日志打印

:::tip 小提示 我们先说几种场景, 看完之后配置规则你自己就有感觉了

注: 下方配置中的 A、B、C 是指 动态任务在Spring中的Bean名称, 可以使用 @Task("xxx") 定义 ruleName1 代表规则名称, :::

异常捕获

在流程配置task-interrupt时,有些开发者不希望任务执行的异常被gobrs-async包装。 而是想亲自进行异常捕获,根据异常类型进行不同业务处理。此时可以配置 异常抛出配置: catchable

    - name: "stopAsyncRule"
      content: "stopAsyncTaskA,stopAsyncTaskB,stopAsyncTaskC;stopAsyncTaskD->stopAsyncTaskE->stopAsyncTaskF"
      catchable: true

规则示例

场景一

如图1-1

场景一

说明 任务A 执行完了之后,继续执行 B、C、D

配置

gobrs:
async:
  rules:
    - name: "ruleName1"
      content: "A->B,C,D"

场景二

如图1-2

场景二

说明 任务A 执行完了之后执行B 然后再执行 C、D

配置

gobrs:
async:
  rules:
    - name: "ruleName1"
      content: "A->B->C,D"

场景三

如图1-3

场景二

说明 任务A 执行完了之后执行B、E 然后按照顺序 B的流程走C、D、G。 E的流程走F、G

配置

gobrs:
async:
  rules:
    - name: "ruleName1"
      content: "A->B->C->D->G;A->E->F->G"

场景四

如图1-4

场景二

说明 这种任务流程 Gobrs-Async 也能轻松支持

配置

gobrs:
async:
  rules:
    - name: "ruleName1"
      content: "A->B->C,D,E;A->H->I,J,K"

场景五

如图1-5

场景二

示例一

说明 A、B、C 执行完之后再执行D

配置

gobrs:
async:
  rules:
    - name: "ruleName1"
      content: "A,B,C->D"

示例二

说明 A、B、C 任务任意一个执行完成,则立即执行任务D( 谁最快执行谁执行, 类似于任务流程竞争关系 ) 此时可以使用 配置关键字 :any

配置

gobrs:
async:
  ## :any 是关键字 表示任意 依赖的任务执行完成立即执行自己
  rules:
    - name: "ruleName1"
      content: "A,B,C->D:any"

示例三

说明 A、B、C 任务任意一个执行完成,则立即执行任务D( 谁最快执行谁执行, 类似于任务流程竞争关系 ) 与示例不同的是, 如果 D拿到执行权后,会将自身所依赖的未完成的任务 强制中断执行(避免浪费资源,业务运行等) 此时可以使用 配置关键字 :exclusive

配置

gobrs:
async:
  ## :exclusive 是关键字
  rules:
    - name: "ruleName1"
      content: "A,B,C->D:any:exclusive"

示例四

同示例二有点类似,在示例二的场景下,无法根据某一个任务的执行成功或者失败进行后续任务的处理,示例二完全根据线程调度执行的随机顺序进行执行,即谁先执行完 谁有资格继续往下执行,所以如果想 执行结果的条件 即: task 方法返回 true 则立即执行,返回false则不执行的判断条件进行控制。那么就有以下的实现方式。

第一步 任务编写

(如果不清楚如何开发一个动态任务,请阅读下一章节:动态任务

    @Override
    public Boolean task(Object o, TaskSupport support) {
        try {
            System.out.println("AServiceCondition Begin");
            Thread.sleep(300);
            for (int i1 = 0; i1 < i; i1++) {
                i1 += i1;
            }
            System.out.println("AServiceCondition Finish");
        } catch (InterruptedException e) {
           // log 打印
           //e.printStackTrace();
           // 返回false 则没有资格执行子任务的逻辑
           return false;
         
        }
        // 返回true 进行执行子任务的逻辑
        return true;
    }

第二步 任务配置

gobrs:
async:
  ## :any 是关键字 表示任意 依赖的任务执行完成立即执行自己
  rules:
    - name: "ruleName1"
      content: "A,B,C->D:anyCondition"

注意

示例三 需要和 示例二配合生效, 因为这两种示例是结合的一种场景。

规则总结

规则配置跟流程图几乎非常相近。

  • 在任务分叉时 使用 , 区分不同任务。
  • 在任务流程发起时 用-> 区分任务流。
  • 每个任务流结束后 用; 进行结束配置。

:::tip 如果你不习惯使用以上配置符号,想自定义在配置符号, 在 Gobrs-Async 中也是支持配置的,可以根据用户使用喜欢进行灵活配置 只需要 在application.yml 中配置即可 :::

如何开发一个异步任务

::: warning 小提示 看到这里,小伙伴们是不是已经迫不及待的想真正的体验一下 Gobrs-Async 是怎样开发一个异步任务的。 那么下面由我带领大家来感受一下 一个完整的 AsyncTask 需要怎么开发。 :::

普通任务

  • 创建 Bean 继承 AsyncTask
  • 标记 @Task 注解

任务标识

如果你想对 任务进行全局拦截 此时就需要对每一个任务加一个特殊的标识,这样在做全局拦截的时候,就可以区分不同的任务,从而执行不同的逻辑。或者进行不同的日志打印 MQ、链路监控等等。 那么 Gobrs-Async 为你提供了支持。 只需要在 任务 Bean 中加上注解, 则会告知框架此 任务的名称 即 全局任务拦截 ,其中 注解中的 name 值对应的就是全局拦截器中参数中的 taskName

@Task(name = "itemTask")

这里 AsyncTask<T, V> 是一个泛型接口

  • T 代表 任务的参数类型
  • V 代表 任务的返回类型

如下:

/**
 * @program: gobrs-async
 * @ClassName TaskBean
 * @description: 异步任务 任务参数 Object类型 ; 任务返回 Object类型
 **/
@Task
public class BService extends AsyncTask<Object, Object> {

    @Override
    public void prepare(Object o) {
        // 任务开始之前的操作 即task 之前
    }

    @Override
    public Object task(Object o, TaskSupport support) {
        String result = getResult(support, AService.class);
        System.out.println("拿到的结果" + result);
        System.out.println("执行BService");
        return null;
    }

    // 什么条件下触发 task执行
    @Override
    public boolean nessary(Object o, TaskSupport support) {
        return true;
    }

    // task执行成功回调用
    @Override
    public void onSuccess(TaskSupport support) {

    }
    
    // task 执行失败 回调
    @Override
    public void onFail(TaskSupport support) {

    }
}

核心任务执行

核心任务为使用者最为关注的功能方法,需要开发RPC、HTTP、IO 等消耗系统资源的业务逻辑。

@Override
public Object task(Object o, TaskSupport support) {
    // todo 业务逻辑
    return null;
}

获取依赖的任务结果

Gobrs-Async 提供了 getResult 方法,无需用户关注如何获取到的依赖结果,只需要按照使用方式便可轻松获取所需结果值

@Override
public Object task(Object o, TaskSupport support) {
    // 拿到 AService (任务bean) 返回的结果, 结果类型为String类型
    String result = getResult(support, AService.class, String.class);
    
    return null;
}

getResult 有三个参数

  • TaskSupport : Gobrs-Async 所需要的核心参数,通过 task 方法中的参数透穿即可
  • Class: 所依赖的 Bean的 Java 类型
  • Class: 返回结果的类型

任务是否执行

Gobrs-Async 会根据 nessary 的返回结果,判断当前task 是否需要执行 如果返回true 则需要被执行,否则返之。

例如: 当参数为 cancel 时, 任务不执行。

@Override
public boolean nessary(String params, TaskSupport support) {
     // 假如参数是cancel 则不执行当前任务
    if("cancel".equals(params)){
        return false;
    }
    return true;
}

任务成功回调

如果你想在任务执行完成后做一些额外的操作。例如打印日志、发送邮件、发送MQ、记录信息等。 Gobrs-Async 同样也为你考虑到了。通过实现 callback 方法。会让你轻松的拿到 任务的执行结果。

@Override
public void onSuccess(TaskSupport support) {
    // todo 任务成功逻辑
}

任务失败回调

在任务异常时发送告警信息

@Override
public void onFail(TaskSupport support) {
    // todo  任务执行失败回调逻辑
}

重试任务

执行中的任务会出现异常的情况,如果使用者有对任务失败重试的需求,Gobrs-Async 也为你提供了支持,只需要在 需要开启重试的任务 bean 中使用 @Task(retryCount = 10) 注解,框架则自动会为你开启重试模式。 retryCount 所跟的数字为 重试次数

@Component
@Task(retryCount = 10)
public class BService extends AsyncTask<Object, Object>  {
// ...
}

单测用例

单测地址

运行结果

2022-12-09 19:36:35.444  INFO 99720 --- [pool-2-thread-1] c.g.a.test.task.retry.CaseRetryTaskA     : caseRetryTaskA 使用线程---pool-2-thread-1
CaseRetryTaskA Begin
CaseRetryTaskA End
2022-12-09 19:36:35.458  INFO 99720 --- [pool-2-thread-1] c.g.a.test.task.retry.CaseRetryTaskC     : caseRetryTaskC 使用线程---pool-2-thread-1
2022-12-09 19:36:35.458  INFO 99720 --- [pool-2-thread-2] c.g.a.test.task.retry.CaseRetryTaskB     : caseRetryTaskB 使用线程---pool-2-thread-2
CaseRetryTaskC Begin
CaseRetryTaskB Begin
CaseRetryTaskC Finish
CaseRetryTaskB Begin
CaseRetryTaskB Begin
CaseRetryTaskB Begin
CaseRetryTaskB Begin
2022-12-09 19:36:35.475 ERROR 99720 --- [pool-2-thread-2] com.gobrs.async.core.task.AsyncTask      : [traceId:11770907551682560] caseRetryTaskB 任务执行失败

java.lang.ArithmeticException: / by zero
	at com.gobrs.async.test.task.retry.CaseRetryTaskB.task(CaseRetryTaskB.java:27) ~[classes/:na]
	at com.gobrs.async.core.task.AsyncTask.taskAdapter(AsyncTask.java:124) ~[classes/:na]
	at com.gobrs.async.core.TaskActuator.call(TaskActuator.java:145) ~[classes/:na]
	at com.alibaba.ttl.TtlCallable.call(TtlCallable.java:58) [transmittable-thread-local-2.11.2.jar:na]
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [na:1.8.0_251]
	at java.util.concurrent.FutureTask.run(FutureTask.java) [na:1.8.0_251]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_251]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_251]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_251]

2022-12-09 19:36:35.476 ERROR 99720 --- [pool-2-thread-2] c.g.a.test.inteceptor.GobrsInterceptor   : Execute global interceptor  error

事务任务

使用者可能有这种事务需求的业务,比如 A -> B -> C 的场景,如果C执行失败了, 则通知 A和B 任务进行业务回滚。 则这种方式 Gobrs-Async 也是支持的 事务任务也需要继承 AsyncTask, 唯一的区别就是以下三个步骤。

只需要在application.yml中配置

application.yml 配置

gobrs:
  async:
    config:
      rules:
        # 规则 是数组类型的 多组规则
        - name: "general"
          content: "AService->BService->FService->GService->HService;EService->CService;AService"
          transaction: true

注解声明

在你需要进行事务的任务上进行回滚注解, Gobrs-Async 会找到 AService 任务链之前的所有任务 回调rollback 方法

@Task(callback = true)
public class AService extend AsyncTask<Object,Object>{
 // ...
}

重写默认rollback方法

//  事务回滚 具体回滚业务需要自己实现 该方法是一个默认方法 需要自己手动重写
@Override
public void rollback(DataContext dataContext) {
    //super.rollback(dataContext);
    //todo rollback business
}

注意 @Task(callback = true) 需要注解在可能触发异常的任务上 官网示例

超时任务

何超时任务? 顾名思义其实就是单一任务可以通过设置超时时间决定改任务是否继续执行。配置方式很简单。如下操作:

注解配置 使用 @Task注解中的 timeoutInMilliseconds 属性进行配置。

  • timeoutInMilliseconds 固定使用毫秒数
package com.gobrs.async.test.task.timeout;
import com.gobrs.async.core.TaskSupport;
import com.gobrs.async.core.anno.Task;
import com.gobrs.async.core.task.AsyncTask;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * The type A service.
 * @program: gobrs -async-starter
 * @description:
 * @author: sizegang
 */
@Slf4j
@Task(timeoutInMilliseconds = 300)
public class CaseTimeoutTaskA extends AsyncTask {

    /**
     * The .
     */
    int i = 10000;

    @Override
    public void prepare(Object o) {
        log.info(this.getName() + " 使用线程---" + Thread.currentThread().getName());
    }

    @SneakyThrows
    @Override
    public String task(Object o, TaskSupport support) {
        System.out.println("CaseTimeoutTaskA Begin");
        Thread.sleep(400);
        for (int i1 = 0; i1 < i; i1++) {
            i1 += i1;
        }
        System.out.println("CaseTimeoutTaskA Finish");
        return "result";
    }

    @Override
    public boolean necessary(Object o, TaskSupport support) {
        return true;
    }

    @Override
    public void onSuccess(TaskSupport support) {
    }
}

超时监听线程池配置

所谓的监听线程池配置即:监听任务超时的线程池的核心线程数,关于为什么要配置该参数。请查看下方的原理分析

gobrs:
  async:
    config:
      rules:
        - name: "chain1"
          content: "taskA->taskB->taskC"
      timeout-core-size: 200 # 核心线程数量

如果不配置则取默认值,默认值计算方式如下:

    public static Integer calculateCoreNum() {
        int cpuCoreNum = Runtime.getRuntime().availableProcessors();
        return new BigDecimal(cpuCoreNum).divide(new BigDecimal("0.2")).intValue();
    }

单例测试

运行代码

运行结果

2022-12-09 16:51:41.031  INFO 37083 --- [pool-2-thread-1] c.g.a.t.task.timeout.CaseTimeoutTaskA    : caseTimeoutTaskA 使用线程---pool-2-thread-1
CaseTimeoutTaskA Begin
2022-12-09 16:51:41.355 ERROR 37083 --- [   GobrsTimer-1] com.gobrs.async.core.timer.GobrsTimer    : 

com.gobrs.async.core.common.exception.TimeoutException: task caseTimeoutTaskA TimeoutException
	at com.gobrs.async.core.TaskLoader$1.tick(TaskLoader.java:394) ~[classes/:na]
	at com.gobrs.async.core.timer.GobrsTimer.lambda$addTimerListener$0(GobrsTimer.java:80) ~[classes/:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_251]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[na:1.8.0_251]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_251]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[na:1.8.0_251]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_251]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_251]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_251]

2022-12-09 16:51:41.375  INFO 37083 --- [pool-2-thread-2] c.g.a.t.task.timeout.CaseTimeoutTaskB    : caseTimeoutTaskB 使用线程---pool-2-thread-2
CaseTimeoutTaskB Begin
CaseTimeoutTaskB Finish
2022-12-09 16:51:41.377  INFO 37083 --- [pool-2-thread-2] c.g.a.t.task.timeout.CaseTimeoutTaskC    : caseTimeoutTaskC 使用线程---pool-2-thread-2
CaseTimeoutTaskC Begin
CaseTimeoutTaskC Finish
2022-12-09 16:51:43.426  INFO 37083 --- [           main] com.gobrs.async.core.TaskLoader          : 【ProcessTrace】Total cost: 2413ms【task】caseTimeoutTaskA cost :312ms【state】:fail【errMsg】: sleep interrupted; ->【task】caseTimeoutTaskB cost :0ms【state】:success; ->【task】caseTimeoutTaskC cost :2011ms【state】:success; 

特别说明

  • 超时任务不支持线程复用,因为需要通过控制线程超时来进行逻辑判断,如果支持线程复用,可能会出现中断正在复用线程的任务执行。
  • 熔断降级原理借鉴Hystrix 方式处理,如果对Hystrix不熟悉可以借鉴 Hystrix 熔断降级原理解析
  • 因线程调度的原因,超时时间可能存在10ms内的误差,可忽略!

线程复用

试想下方任务流程中,在理想情况下最少用几个线程即可完成流程的执行? taskA->taskB,TaskC->taskD->taskE,taskF 是6个线程 还是5、4、3、2 你可能已经想到了答案是 2个线程(main线程除外)即可完成该复杂的多线程流程。 为什么呢? 因为在并发执行时, TaskB、TaskC 又或者是 TaskE、TaskF 都只有两个并发的任务同时存在,所以决定使用线程数量个数的根本条件是有多少个并发任务同时执行 那么看下gobrs-async 此时有多少个线程在执行

ccc

测试用例

地址

运行结果

主线程使用main
使用main
TaskA
2022-12-11 13:58:22.581  INFO 8039 --- [           main] com.gobrs.async.core.task.AsyncTask      : <11780902254572224> [taskA] execution
使用main
TaskC
使用pool-2-thread-1
TaskB
2022-12-11 13:58:22.694  INFO 8039 --- [           main] com.gobrs.async.core.task.AsyncTask      : <11780902254572224> [TaskC] execution
2022-12-11 13:58:22.694  INFO 8039 --- [pool-2-thread-1] com.gobrs.async.core.task.AsyncTask      : <11780902254572224> [taskB] execution
使用pool-2-thread-1
TaskD
2022-12-11 13:58:22.804  INFO 8039 --- [pool-2-thread-1] com.gobrs.async.core.task.AsyncTask      : <11780902254572224> [taskD] execution
使用pool-2-thread-1
使用pool-2-thread-2
TaskE
2022-12-11 13:58:22.909  INFO 8039 --- [pool-2-thread-2] com.gobrs.async.core.task.AsyncTask      : <11780902254572224> [taskE] execution
TaskF
2022-12-11 13:58:22.910  INFO 8039 --- [pool-2-thread-1] com.gobrs.async.core.task.AsyncTask      : <11780902254572224> [taskF] execution
2022-12-11 13:58:22.913  INFO 8039 --- [           main] com.gobrs.async.core.TaskLoader          : 【ProcessTrace】Total cost: 440ms | traceId = 11780902254572224 | 【task】taskA cost :103ms【state】:success; ->【task】taskB cost :103ms【state】:success; ->【task】TaskC cost :103ms【state】:success; ->【task】taskD cost :106ms【state】:success; ->【task】taskE cost :101ms【state】:success; ->【task】taskF cost :101ms【state】:success; 
耗时462

说明

通过日志可以看到 TaskC使用了 TaskA的线程执行任务, 因TaskB 和 TaskC是并行的, 所以此时需要开辟新线程执行TaskB,等到TaskB执行完成后, TaskD继续使用 TaskB的 线程 pool-2-thread-1 执行任务, 此时TaskC执行完成后 发现其子任务已经被 TaskB释放后的线程拿到执行权,则不需要使用自身线程执行任务。 同理任务流程 继续往下执行。 整个流程中一共使用 3个线程(包含main线程)。

小编对比业界多种多线程并发框架,目前只有gobrs-Async 具备线程复用的能力。 具体测试用例在下方性能测试章节展示。

日志体系

使用 log.error(getFormattedTraceId(), exception); 打印的日志会自动带上 traceId, getFormattedTraceIdAsyncTask 提供的通用方法。

@Slf4j
@Task(failSubExec = true)
public class BService extends AsyncTask {

    int i = 10000;
    @Override
    public void prepare(Object o) {
        log.info(this.getName() + " 使用线程---" + Thread.currentThread().getName());
    }

    @Override
    public Object task(Object o, TaskSupport support) {
        System.out.println("BService Begin");
        for (int i1 = 0; i1 < i; i1++) {
            i1 += i1;
        }
        try {
            System.out.println(1 / 0);
        } catch (Exception exception) {
            log.error(getFormattedTraceId(), exception);
        }

        System.out.println("BService Finish");
        return null;
    }
}

开启全局日志打印

  • costLogabled:打印任务流程的全链路执行过程
  • errLogabled:开启任务异常打印 默认true
gobrs:
  async:
    config:
      rules:
        - name: "optionalRule"
          content: "caseOptionalTaskA->caseOptionalTaskB->caseOptionalTaskC,caseOptionalTaskD->caseOptionalTaskE->caseOptionalTaskF"
          task-interrupt: false # 局部异常是否打断主流程 默认false
          transaction: false
          logConfig:
            costLogabled: true # 开启任务耗时打印 log日志级别需要为 error 默认true
            errLogabled: true # 开启任务异常打印 默认true

打印效果

CaseOptionalTaskA 任务执行
CaseOptionalTaskA 任务执行完成
2022-12-11 15:47:32.511  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.task.AsyncTask      :  <11781331511388032> [caseOptionalTaskA] execution
CaseOptionalTaskB 任务执行
CaseOptionalTaskB 任务执行完成
2022-12-11 15:47:32.613  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.task.AsyncTask      :  <11781331511388032> [caseOptionalTaskB] execution
CaseOptionalTaskD 任务执行
CaseOptionalTaskD任务执行完成
2022-12-11 15:47:32.718  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.task.AsyncTask      :  <11781331511388032> [caseOptionalTaskD] execution
2022-12-11 15:47:32.718  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.TaskLoader          : 【ProcessTrace】Total cost: 311ms | traceId = 11781331511388032 | 【task】caseOptionalTaskA cost :102ms【state】:success; ->【task】caseOptionalTaskB cost :102ms【state】:success; ->【task】caseOptionalTaskD cost :105ms【state】:success; 
cost 311

第三方日志框架集成

这里选择Tlog 日志框架, 使用方法这里就不做赘述了。感兴趣的小伙伴可以到官网查看

集成使用

/**
 * 启动类
 */
@SpringBootApplication
/**
 * 使用gobrs-async-test 模块创建的任务 为了方便不重复创建任务了
 */
@ComponentScan(value = {"com.gobrs.async"})
public class GobrsAsyncExampleApplication {

    /**
     * Tlog 日志打印框架 官网: https://tlog.yomahub.com/
     */
    static {
        AspectLogEnhance.enhance();
    }

    /**
     * The entry point of application.
     *
     * @param args the input arguments
     */
    public static void main(String[] args) {
        SpringApplication.run(GobrsAsyncExampleApplication.class, args);
    }
}

更多细节

集成方式请参考源码示例项目 gobrs-async-example 或者直接下载源码查看。 源码地址

规则热更新

在Gobrs-Async中默认规则只会加载一次,可能有朋友可能会有规则动态变化的需求,使用程序动态修改规则配置。而不需要重新启动程序。那么对于这种需求 Gobrs-Async 同样支持。

Gobrs-Async 默认使用CopyOnWrite 机制更新的规则配置,并发度更高。同时维护了线程安全机制。

// 规则热加载器
@Resource
private RuleThermalLoad ruleThermalLoad;

// 热更新规则任务 无需启动程序, 只需要将规则交给 规则热加载器 即可完成接入
public void updateRule(Rule rule) {
    // 单任务修改
    Rule r = new Rule();
    r.setName("ruleName");
    r.setContent("AService->CService->EService->GService; BService->DService->FService->HService;");
    ruleThermalLoad.load(rule);
    
    // 批量修改 
    List<Rule> updateRules = new ArrayList<Rule>();
    updateRules.add(r);
    // updateRules.add(...);
    ruleThermalLoad.load(updateRules);
}

验证

如果日志打印如下提示,说明配置热更新成功

com.gobrs.async.engine.RuleThermalLoad   : rule test update success

中断状态码

在流程中如果你想在某种业务场景下手动关闭任务流程执行。 并在任务触发器执行完成之后,根据AsyncResult 的结果,判断不同的业务逻辑 Gobrs-Async 也为你提供了途径。 用户只需要在 异步任务的 task方法中 手动跳用 stopAsync 透传TaskSupport 无需关注内部实现,即可轻松完成关闭主流程。

stopAsync 方法有两个参数说明如下:

  • TaskSupport: Gobrs-Async 使用参数, 透传即可。
  • expCode : 中断状态码,可自定义枚举
    @Override
    public Map task(DataContext dataContext, TaskSupport support) {
        try {
            // todo 执行任务
        } catch (Exception e) {
             // todo  根据不同的异常 处理返回不同的 中断码
            if (e instanceof RedirectSimpleException) {
                // 中断任务流程
                stopAsync(support, PRODUCT_NOT_FOUND);
                return null;
            }
            stopAsync(support, SYSTEM_DEMOTION);
        }
        return null;
    }

任务触发器执行完成 执行完成之后,会获取 AsyncResult 任务流程执行结果。 根据不同的中断码,执行不同的业务逻辑。

Map<String, Object> params  = new HashMap();
// 任务流程名称 , 任务流程传入参数, 任务流程超时时间 
AsyncResult asyncResult = gobrsAsync.go("ruleName", () -> params, timeOut);

if(asyncResult.getExpCode().equals(100)){
    // 业务一
}else if(asyncResult.getExpCode().equals(200)){
    // 业务二
}

任务异常是否中断子任务流程

在执行 A->B->C 过程中,如果A 执行异常,Gobrs-Async 默认不会继续执行 B、C任务了,但是如果使用者有特殊需求, 想要继续执行 B、C任务, 这种情况Gobrs-Async 也提供支持, 只需要在 Task注解中声明 failSubExec 即可继续执行任务流程。 默认 failSubExec=false

@Service
@Task(failSubExec = true) 
public class BService extends AsyncTask<Object, Object>  {
// ...
}

状态任务流程

何为状态任务流程? 其实很好理解,比如说有 A、B、C、D 四个任务。D任务的执行依赖A、B、C三个任务, 但是A B C 的执行状态有不好确定(运行时状态) 如果想根据任务返回值的状态决定流程如何执行怎么办呢? 比如说A B C三个任务中根据不通的业务逻辑会返回不通的任务状态。遇到这种情况可以使用Gobrs-Async 为你提供的动态状态能力选择任务执行。 比如: A 业务返回true 则就执行D任务,无需关心B、C任务的执行过程。

与开发一个普通任务不通的是,返回结果需要是 AnyConditionResult 类型。

package com.gobrs.async.test.task.condition;

import com.gobrs.async.core.TaskSupport;
import com.gobrs.async.core.anno.Task;
import com.gobrs.async.core.common.domain.AnyConditionResult;
import com.gobrs.async.core.task.AsyncTask;
import org.springframework.stereotype.Component;

/**
 * The type A service.
 *
 * @program: gobrs -async-starter
 * @ClassName AService
 * @description: 任务依赖类型
 * AServiceCondition,BServiceCondition,CServiceCondition->DServiceCondition:anyCondition
 * <p>
 * 简化配置
 * <p>
 * A,B,C->D:anyCondition
 * <p>
 * D根据 A,B,C 返回的任务结果中的 AnyCondition 的state状态 进行判断是否继续执行 子任务。
 * @author: sizegang
 * @create: 2022 -03-20
 */
@Task(failSubExec = true)
public class AServiceCondition extends AsyncTask {
    /**
     * The .
     */
    int sums = 10000;
    @Override
    public AnyConditionResult<String> task(Object o, TaskSupport support) {
        AnyConditionResult.Builder<String> builder = AnyConditionResult.builder();
        try {
            System.out.println("AServiceCondition Begin");
            Thread.sleep(300);
            for (int i1 = 0; i1 < sums; i1++) {
                i1 += i1;
            }
            System.out.println("AServiceCondition Finish");
        } catch (InterruptedException e) {
            e.printStackTrace();
            //  异常返回false
           return builder.setState(false).build();
        }
        return builder.setState(true).build();
    }
}

AnyConditionResult.Builder<String> builder = AnyConditionResult.builder(); 构造函数默认创建一个 true的状态。

单测用例

单测地址

运行结果

2022-12-09 17:48:44.676  INFO 58639 --- [           main] com.gobrs.async.core.GobrsPrint          : Gobrs-Async Load Successful
CServiceCondition Begin
BServiceCondition Begin
AServiceCondition Begin
BServiceCondition Finish
AServiceCondition Finish
DServiceCondition Begin
DServiceCondition Finish
2022-12-09 17:48:45.435  INFO 58639 --- [pool-1-thread-1] com.gobrs.async.core.TaskLoader          : 【ProcessTrace】Total cost: 334ms | traceId = 11770483512420224 | 【task】BServiceCondition cost :3ms【state】:success; ->【task】AServiceCondition cost :305ms【state】:success; ->【task】DServiceCondition:anyCondition cost :0ms【state】:success; 
377
【gobrs-async】 testCondition 执行完成

可配置的全局异常拦截器

如果你想在任务流程执行过程中,某一任务执行异常,想让整个任务流程停止下来。并且可自定拦截这个异常,可在发生异常时 执行报警或者打印异常等业务。

开启全局异常拦截

配置application.yml

gobrs:
  async:
    config:
      rules:
        # 规则 是数组类型的 多组规则
        - name: "general"
          content: "AService->BService->FService->GService->HService;EService->CService;AService"
          task-interrupt: true # 局部异常是否打断主流程 默认 false

异常拦截器

实现 AsyncExceptionInterceptor 接口,开发一个自定义的异常处理拦截器

/**
 * @program: gobrs-async
 * @ClassName GobrsExceptionInter
 * @description: 主流程中断异常自定义处理
 * @author: sizegang
 * @create: 2022-02-19 22:55
     * @Version 1.0
 **/
@Component
public class GobrsExceptionInter implements AsyncTaskExceptionInterceptor {

    @Override
    public CompletionException exception(Throwable throwable, Boolean state) {
        System.out.println("自定义全局异常 exceptor Interceptor 触发");
        return new CompletionException(throwable);
    }
}

默认情况

默认 Gobrs-Async 对全局拦截器开关是关闭的,如果流程中某一任务异常,只会停止所依赖该异常任务的任务停止,并调用callback 通知 下游任务

可配置的全局任务拦截器

有些小伙伴可能不满足与单任务的拦截,希望有一个统一拦截的入口,而不是对每一个任务做单独的处理。那么 Gobrs-Async 也为您提供了支持。

前置全局任务流程拦截器

实现 AsyncTaskPreInterceptor 接口,开发一个自定义的任务流程前置 全局拦截器。

/**
 * @program: m-detail
 * @ClassName AsyncTaskPreInterceptor
 * @description:
 * @author: sizegang
 * @create: 2022-03-24
 **/
@Component
public class TaskPreInterceptor implements AsyncTaskPreInterceptor<DataContext> {
    
     /**
     * 
     * @param params 参数
     * @param taskName 任务名称
     */
    @Override
    public void preProcess(DataContext params, String taskName) {

    }
}

后置全局任务流程拦截器

实现 TaskPostInterceptor 接口,开发一个自定义的任务流程前置 全局拦截器

/**
 * @program: m-detail
 * @ClassName AsyncTaskPreInterceptor
 * @description:
 * @author: sizegang
 * @create: 2022-03-24
 **/
@Component
public class TaskPostInterceptor implements AsyncTaskPostInterceptor {
    /**
     *
     * @param result 任务结果
     * @param taskName 任务名称
     */
    @Override
    public void postProcess(Object result, String taskName) {

    }
}

自定义固定线程池

Gobrs-Async 默认使用的是 Executors.newCachedThreadPool() 的线程池, 如果你想自定义线程池。满足自己的线程池需求。 只需要 GobrsAsyncThreadPoolFactory 对象,如下:

@Configuration
public class ThreadPoolConfig {

    @Autowired
    private GobrsAsyncThreadPoolFactory factory;
    
    @PostConstruct
    public void gobrsThreadPoolExecutor(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(300, 500, 30, TimeUnit.SECONDS,
                new LinkedBlockingQueue());
        factory.setThreadPoolExecutor(threadPoolExecutor);
    }

实时更新线程池

开发者可能有这种苦恼,线程池在运行时是在项目初始化的时候从application.yml中 加载的, 一旦程序运行起来之后,就无法修改使用的线程池了。 如果自己公司有分布式配置中心,可以实时更新程序内存的应用的话,那么gobrs也为你提供了入口。

在我们公司是有自己的热更新组件的,所有可以如下使用:

配置中心的线程池配置

{
corePoolSize: 210,
maxPoolSize: 600,
keepAliveTime: 30,
capacity: 10000,
threadNamePrefix: "m-detail"
rejectedExecutionHandler: "CallerRunsPolicy"
}
@Slf4j
@Configuration
public class ThreadPoolConfig {

    @Autowired
    private GobrsAsyncThreadPoolFactory factory;

    @Resource
    private DUCCConfigService duccConfigService;

    @PostConstruct
    public void gobrsThreadPoolExecutor() {
        // 从配置中心拿到 线程池配置规则 DuccConstant.GOBRS_ASYNC_THREAD_POOL 为线程池配置在配置中心的key
        String config = duccConfigService.getString(DuccConstant.GOBRS_ASYNC_THREAD_POOL);
        ThreadPool threadPool = JSONObject.parseObject(config, ThreadPool.class);
         
        // 通过gobrs-async 提供的构造器进行构造线程池
        ThreadPoolExecutor executor = ThreadPoolBuilder.buildByThreadPool(threadPool);
        factory.setThreadPoolExecutor(executor);
        listenerDucc();
    }
    
    // 监听配置中心 线程池改动
    private void listenerDucc() {
        duccConfigService.addListener(new DuccListener(DuccConstant.GOBRS_ASYNC_THREAD_POOL, property -> {
            log.warn("监听到DUCC配置GobrsAsync 线程池配置变更,property:{}", JSON.toJSONString(property.getValue()));
            ThreadPool threadPool = JSONObject.parseObject(property.getValue().toString(), ThreadPool.class);
            ThreadPoolExecutor executor = ThreadPoolBuilder.buildByThreadPool(threadPool);
            factory.setThreadPoolExecutor(executor);
            // 线程池更新成功
            log.warn("GobrsAsync thread pool update success");
        }));
    }

}

可选的执行流程

任务配置

- name: "optionalRule"
  content: "caseOptionalTaskA->caseOptionalTaskB->caseOptionalTaskC,caseOptionalTaskD->caseOptionalTaskE->caseOptionalTaskF"

如果开发者在调用时只希望执行 caseOptionalTaskD , 则在任务链中 只需要执行caseOptionalTaskA、caseOptionalTaskB、caseOptionalTaskD 三个任务即可即可。 其他任务不需要执行 ,提供了随机选择流程中任务执行的能力。

调用方式

gobrsAsync.go方法的第三个参数 Set<String> 需要传递 要执行的任务 bean 名称。

    @Test
    public void testOptional() {
        Map<Class, Object> params = new HashMap<>();
        Set<String> options = new HashSet<>();
        options.add("caseOptionalTaskD"); # options中添加要执行的任务 bean 名称
        AsyncResult asyncResult = gobrsAsync.go("optionalRule", () -> params, options, 300000);
    }

测试用例

源码地址

运行结果

CaseOptionalTaskA 任务执行
CaseOptionalTaskA 任务执行完成
2022-12-11 15:47:32.511  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.task.AsyncTask      : <0><11781331511388032> <11781331511388032> [caseOptionalTaskA] execution
CaseOptionalTaskB 任务执行
CaseOptionalTaskB 任务执行完成
2022-12-11 15:47:32.613  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.task.AsyncTask      : <0><11781331511388032> <11781331511388032> [caseOptionalTaskB] execution
CaseOptionalTaskD 任务执行
CaseOptionalTaskD任务执行完成
2022-12-11 15:47:32.718  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.task.AsyncTask      : <0><11781331511388032> <11781331511388032> [caseOptionalTaskD] execution
2022-12-11 15:47:32.718  INFO 13458 --- [o-8888-exec-152] com.gobrs.async.core.TaskLoader          : <0><11781331511388032> 【ProcessTrace】Total cost: 311ms | traceId = 11781331511388032 | 【task】caseOptionalTaskA cost :102ms【state】:success; ->【task】caseOptionalTaskB cost :102ms【state】:success; ->【task】caseOptionalTaskD cost :105ms【state】:success; 
cost 311

适应场景

在做 ISV (京东商城ISV组件化建设) 建设时, 楼层中的多个组件可能存在着任务流程的编排, 所需要的上游数据数量多少不一,所以此时就需要进行编排流程中的任务选择执行处理了。 如下对每个组件进行编排数据编排处理。 image-20220809222627074

插件

监控系列

skywalking 适配器

skywalking 是全链路监控平台,因为skywalking 不兼容多线程traceId,所以gobrs-async 提供skywalking插件

使用方式

pom.xml 依赖引入

<dependency>
    <groupId>io.github.memorydoc</groupId>
    <artifactId>gobrs-async-skywalking-plugin</artifactId>
    <version>1.2.9-RELEASE</version>
</dependency>

只需引入依赖即可完成与skywalking完美适配。是不是感觉很神奇!

日志系列

全链路traceId

各位开发同学已经都知道,全链路traceId是打印在日志里的方便链路追踪的序列号。 有了它你可以轻松追踪线上问题,简单好用。

使用方式

pom.xml 依赖引入

<dependency>
    <groupId>io.github.memorydoc</groupId>
    <artifactId>gobrs-async-trace-plugin</artifactId>
    <version>1.2.9-RELEASE</version>
</dependency>

只需引入依赖即可完成与skywalking完美适配。是不是感觉很神奇!

静态注入

需要在SpringBoot启动类中编写

static {
    GobrsLogger.logger();
}

说明

Gobrs-Async日志插件封装了 Tlog 如有使用问题请访问Tlog官网。

加群沟通

对于这个项目,是否有什么不一样看法,欢迎在 Issue 一起沟通交流; 群二维码七天会失效,可以添加作者微信进交流群





贡献者

More Repositories

1

hutool

🍬A set of tools that keep Java sweet.
Java
28,241
star
2

Sa-Token

这可能是史上功能最全的Java权限认证框架!目前已集成——登录认证、权限认证、分布式Session会话、微服务网关鉴权、单点登录、OAuth2.0、踢人下线、Redis集成、前后台分离、记住我模式、模拟他人账号、临时身份切换、账号封禁、多账号认证体系、注解式鉴权、路由拦截式鉴权、花式token生成、自动续签、同端互斥登录、会话治理、密码加密、jwt集成、Spring集成、WebFlux集成...
Java
15,305
star
3

lamp-cloud

lamp-cloud 基于Jdk11 + SpringCloud + SpringBoot 开发的微服务中后台快速开发平台,专注于多租户(SaaS架构)解决方案,亦可作为普通项目(非SaaS架构)的基础开发框架使用,目前已实现插拔式数据库隔离、SCHEMA隔离、字段隔离 等租户隔离方案。
Java
5,311
star
4

hertzbeat

A real-time monitoring system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities.
Java
4,459
star
5

hmily

Distributed transaction solutions
Java
4,086
star
6

dynamic-tp

🔥🔥🔥轻量级动态线程池,内置监控告警功能,集成三方中间件线程池管理,基于主流配置中心(已支持Nacos、Apollo,Zookeeper、Consul、Etcd,可通过SPI自定义实现)。Lightweight dynamic threadpool, with monitoring and alarming functions, base on popular config centers (already support Nacos、Apollo、Zookeeper、Consul, can be customized through SPI).
Java
3,453
star
7

liteflow

Lightweight, fast, stable, and programmable component-based rule engine/process engine. Component reuse, synchronous/asynchronous orchestration, dynamic orchestration, multi-language scripting support, complex nested rules, hot deployment, smooth refreshing. Let you improve your development efficiency!
Java
2,610
star
8

raincat

强一致分布式事务框架
Java
1,908
star
9

mayfly-go

web版linux(终端 文件 脚本 进程)、数据库(mysql pgsql oracle sqlserver 高斯 达梦 sqlite)、数据同步、redis(单机 哨兵 集群)、mongo统一管理操作平台。web version of linux(terminal file script process), database (mysql pgsql oracle sqlserver Gauss sqlite), redis(single sentinel cluster), mongo unified management and operation platform.
Vue
1,657
star
10

forest

A high-level and lightweight declarative HTTP client framework for Java. it makes sending HTTP requests in Java easier.
Java
1,568
star
11

electron-egg

A simple, cross platform, enterprise desktop software development framework
JavaScript
1,517
star
12

myth

Reliable messages resolve distributed transactions
Java
1,492
star
13

easy-es

A foolproof Elasticsearch ORM framework that is easy to use, requires minimal coding, and is highly expandable...
Java
1,300
star
14

MaxKey

🗝️MaxKey SSO ,Leading-Edge IAM-IDaas(Identity and Access Management) Product,业界领先的IAM-IDaas身份管理和认证产品,支持OAuth2.x、OpenID Connect、SAML2.0、JWT、CAS、SCIM等SSO标准协议,基于RBAC统一权限控制,实现用户生命周期管理,开源、安全、合规、自主可控。
Java
1,234
star
15

Jpom

🚀简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件
Java
1,184
star
16

x-file-storage

一行代码将文件存储到 本地、FTP、SFTP、WebDAV、谷歌云存储、阿里云OSS、华为云OBS、七牛云Kodo、腾讯云COS、百度云 BOS、又拍云USS、MinIO、 AWS S3、FastDFS、 Azure Blob Storage、金山云 KS3、美团云 MSS、京东云 OSS、天翼云 OOS、移动云 EOS、沃云 OSS、 网易数帆 NOS、Ucloud US3、青云 QingStor、平安云 OBS、首云 OSS、IBM COS、其它兼容 S3 协议的平台。后续即将支持 Samba、NFS
Java
1,042
star
17

sureness

A simple and efficient security framework that focus on protection of API.
Java
844
star
18

RuoYi-Vue-Plus

基于RuoYi-Vue集成 Lombok+Mybatis-Plus+Undertow+knife4j+Hutool+Feign 重写所有原生业务 定期与RuoYi-Vue同步
Java
776
star
19

payment-spring-boot

微信支付V3支付,支持微信优惠券,代金券、商家券、公众号支付、微信小程序支付、分账、支付分、商家券、合单支付、先享卡、电商收付通等全部微信支付功能API,同时满足服务商、商户开发需求。一键集成,上手快,欢迎star。
HTML
706
star
20

mendmix-cloud

Mendmix定位是一站式分布式开发架构开源解决方案及云原生架构技术底座。Mendmix提供了数据库、缓存、消息中间件、分布式定时任务、安全框架、网关以及主流产商云服务快速集成能力。基于Mendmix可以不用关注技术细节快速搭建高并发高可用基于微服务的分布式架构。
Java
694
star
21

SMS4J

让简单的事情回归简单的本质。 SMS4J为短信聚合框架,帮您轻松集成多家短信服务,解决接入多个短信SDK的繁琐流程。 目前已接入数家常见的短信服务商,后续将会继续集成。后续的版本中我们还将推出更多的相关功能 你的 ⭐️ ⭐️⭐️Star⭐️⭐️ ⭐️,是我的动力!如果你觉得还不错,请点上一颗小星星
Java
662
star
22

dante-cloud

Dante Cloud 是以「高质量代码、低安全漏洞」为核心,采用领域驱动模型(DDD)设计思想,完全基于 Spring 生态全域开源技术和 OAuth2.1 协议,支持智能电视、IoT等物联网设备认证,满足国家三级等保要求、支持接口国密数字信封加解密、防刷、高防XSS和SQL注入等一系列安全体系的多租户微服务解决方案。
Java
626
star
23

RuoYi-Cloud-Plus

重写RuoYi-Cloud所有功能 整合 SpringCloudAlibaba Dubbo3.0 Sa-Token Mybatis-Plus MQ OSS ES Xxl-Job Docker 全方位升级 定期同步
Java
547
star
24

TLog

Lightweight distributed log label tracking framwork
Java
529
star
25

yft-design

一款美观且功能强大的在线设计工具,具备海报设计和图片编辑功能,基于fabric.js的开源版【稿定设计】。适用于多种场景,如海报生成、电商产品图制作、文章长图设计、视频/公众号封面编辑等 。A beautiful and powerful online design tool
TypeScript
491
star
26

go-view

GoView 说明文档,GoView 是一个低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可完成业务需求。 它的技术栈为:Vue3 + TypeScript4 + Vite2 + NaiveUI + ECharts5 + Axios + Pinia2 + PlopJS
Vue
472
star
27

fast-request

IntelliJ IDEA plugin Restful Fast Request
Shell
431
star
28

neutrino-proxy

中微子代理(内网穿透)
Java
418
star
29

tianai-captcha

可能是java界最好的开源行为验证码 [滑块验证码、点选验证码、行为验证码、旋转验证码, 滑动验证码]
Java
413
star
30

newcar

🪢A modern animation engine for JavaScript ecosystem, which is based on CanvasKit-WASM.
TypeScript
389
star
31

CloudEon

CloudEon uses Kubernetes to install and deploy open-source big data components, enabling the containerized operation of an open-source big data platform. This allows you to reduce your focus on underlying resource management and maintenance.
Java
375
star
32

disjob

A distributed job scheduling and distributed computing framework
Java
329
star
33

Jinx

Spring-boot框架采用netty取代tomcat 来做http服务
Java
292
star
34

cubic

一站式问题定位平台,还在为线上问题而烦恼吗?分布式实例监控、线程栈监控、线程池监控、动态arthas命令集、依赖分析等等等,助你快速定位问题
Java
244
star
35

dataCompare

big data comparison and data profiling platform: low code,data comparison and data profiling
Java
231
star
36

RedisFront

RedisFront 是一款开源免费的跨平台 Redis 桌面客户端工具, 支持单机模式, 集群模式, 哨兵模式以及 SSH 隧道连接, 欢迎下载使用.
Java
215
star
37

northstar

国内最优秀的基于JAVA的AI开源量化交易平台,秒替文华、MC、金字塔。具备历史回放、策略研发、模拟交易、实盘交易等功能。兼顾全自动与半自动的使用场景。
Java
202
star
38

issues-translate-action

The action for translating Non-English issues content to English.
TypeScript
174
star
39

hodor

A distributed scheduling job framework supporting DAG workflow for big data and regular jobs, providing programmable job types across different languages.
Java
136
star
40

distribute-transaction

分布式事务书籍随书源码
Java
98
star
41

koalas-rpc

企业生产级百亿日PV高可用可拓展的RPC框架。理论上并发数量接近服务器带宽,客户端采用thrift协议,服务端支持netty和thrift的TThreadedSelectorServer半同步半异步线程模型,支持动态扩容,服务上下线,权重动态,可用性配置,泛化调用,页面流量统计,泛化调用等,支持trace跟踪等,天然接入cat支持数据大盘展示等,持续为个人以及中小型公司提供可靠的RPC框架技术方案
Java
98
star
42

stream-query

Java
89
star
43

dax-pay

免费开源的支付网关,支持支付宝、微信、云闪付等通道,提供收单、退款、聚合支付、组合支付、对账、分账等功能,同时扩展了更多支付方式,如储值卡、现金卡等,通过HTTP方式进行调用,不与其他系统产生耦合关联,可以快速集成到各种系统中,提供可视化界面进行管理,便于实现统一的支付信息管理。
Java
78
star
44

J2EEFAST

J2eeFAST 是一个 Java EE 企业级快速开发平台,永久免费、真开源,拒绝标题党。基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。 在线代码生成功能,包括核心模块如:组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、license认证,BPM工作流等。采用松耦合设计;界面无刷新,一键换肤;众多账号安全设置,密码策略;在线定时任务配置;支持多数据源;支持读写分离、分库分表.
Java
77
star
45

TestHub

一款基于流程编排的自动化测试工具
Java
39
star
46

binlog4j

Java
33
star
47

dromara.github.io

Dromara Official Website
TypeScript
32
star
48

mybatis-plus-ext

mybatis-plus框架的拓展包,在框架原有基础上做了进一步的轻度封装,增强内容:多数据源自动建表、数据自动填充、自动关联查询、冗余数据自动更新、动态查询条件等。
Java
29
star
49

athena

Java
22
star
50

WeMQ

WeMQ是一款面向物联网设备运营商的开源物联网设备调试系统,提供完整的物联网设备调试方案,集成设备管理、MQTT服务器管理、客户管理等功能,自研Nmqs通信层组件,实现了连接信息的加密,保证了数据的安全性。
HTML
18
star
51

open-capacity-platform

JavaScript
14
star
52

transaction-book

distributed transaction book
12
star
53

mybatis-jpa-extra

简化MyBatis CUID操作,增强SELECT分页查询
Java
10
star
54

website

Dromara Official Website (Old)
JavaScript
7
star
55

hmily-admin

Java
7
star
56

plus-doc

HTML
4
star
57

soul-benchmark

Soul performance test
3
star
58

gateway-book

2
star
59

hmily-dashboard

Vue
2
star
60

open-giteye-api

Java
2
star
61

skyway

2
star
62

hmily-admin-helm-chart

Smarty
2
star
63

tlog-homepage

JavaScript
1
star
64

soul-doc

1
star
65

northstar-monitor

JavaScript
1
star
66

stream-query-docs

文档
HTML
1
star