PowerJob的DesignateServer工作流程源码解读

 更新时间:2024年01月18日 10:33:54   作者:codecraft  
这篇文章主要介绍了PowerJob的DesignateServer工作流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下PowerJob的DesignateServer

DesignateServer

tech/powerjob/server/remote/server/redirector/DesignateServer.java

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DesignateServer {

    /**
     * 转发请求需要 AppInfo 下的 currentServer 信息,因此必须要有 appId 作为入参,该字段指定了 appId 字段的参数名称,默认为 appId
     * @return appId 参数名称
     */
    String appIdParameterName() default "appId";
}
DesignateServer注解定义了appIdParameterName属性,默认是appId

DesignateServerAspect

tech/powerjob/server/remote/server/redirector/DesignateServerAspect.java

@Slf4j
@Aspect
@Component
@Order(0)
@RequiredArgsConstructor
public class DesignateServerAspect {
    private final TransportService transportService;
    private final AppInfoRepository appInfoRepository;
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    @Around(value = "@annotation(designateServer))")
    public Object execute(ProceedingJoinPoint point, DesignateServer designateServer) throws Throwable {
        // 参数
        Object[] args = point.getArgs();
        // 方法名
        String methodName = point.getSignature().getName();
        // 类名
        String className = point.getSignature().getDeclaringTypeName();
        Signature signature = point.getSignature();
        // 方法签名
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] parameterNames = methodSignature.getParameterNames();
        String[] parameterTypes = Arrays.stream(methodSignature.getParameterTypes()).map(Class::getName).toArray(String[]::new);
        Long appId = null;
        for (int i = 0; i < parameterNames.length; i++) {
            if (StringUtils.equals(parameterNames[i], designateServer.appIdParameterName())) {
                appId = Long.parseLong(String.valueOf(args[i]));
                break;
            }
        }
        if (appId == null) {
            throw new PowerJobException("can't find appId in params for:" + signature);
        }
        // 获取执行机器
        AppInfoDO appInfo = appInfoRepository.findById(appId).orElseThrow(() -> new PowerJobException("can't find app info"));
        String targetServer = appInfo.getCurrentServer();
        // 目标IP为空,本地执行
        if (StringUtils.isEmpty(targetServer)) {
            return point.proceed();
        }
        // 目标IP与本地符合则本地执行
        if (Objects.equals(targetServer, transportService.defaultProtocol().getAddress())) {
            return point.proceed();
        }
        log.info("[DesignateServerAspect] the method[{}] should execute in server[{}], so this request will be redirect to remote server!", signature.toShortString(), targetServer);
        // 转发请求,远程执行后返回结果
        RemoteProcessReq remoteProcessReq = new RemoteProcessReq()
                .setClassName(className)
                .setMethodName(methodName)
                .setParameterTypes(parameterTypes)
                .setArgs(args);
        final URL friendUrl = ServerURLFactory.process2Friend(targetServer);
        CompletionStage<AskResponse> askCS = transportService.ask(Protocol.HTTP.name(), friendUrl, remoteProcessReq, AskResponse.class);
        AskResponse askResponse = askCS.toCompletableFuture().get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        if (!askResponse.isSuccess()) {
            throw new PowerJobException("remote process failed: " + askResponse.getMessage());
        }
        // 考虑范型情况
        Method method = methodSignature.getMethod();
        JavaType returnType = getMethodReturnJavaType(method);
        return OBJECT_MAPPER.readValue(askResponse.getData(), returnType);
    }
    //......
}
DesignateServerAspect拦截了@DesignateServer注解,它先解析方法参数名,取出参数名与@DesignateServer的appIdParameterName一致的参数值,再通过appInfoRepository.findById找到AppInfoDO,获取appInfo.getCurrentServer();若currentServer就是本机则执行point.proceed(),否则构建RemoteProcessReq,通过transportService.ask转发请求

示例

tech/powerjob/server/core/instance/InstanceLogService.java

/**
     * 获取日志的下载链接
     * @param appId AOP 专用
     * @param instanceId 任务实例 ID
     * @return 下载链接
     */
    @DesignateServer
    public String fetchDownloadUrl(Long appId, Long instanceId) {
        String url = "http://" + NetUtils.getLocalHost() + ":" + port + "/instance/downloadLog?instanceId=" + instanceId;
        log.info("[InstanceLog-{}] downloadURL for appId[{}]: {}", instanceId, appId, url);
        return url;
    }
fetchDownloadUrl指定了@DesignateServer注解,会根据appId的值限定在指定server执行

小结

PowerJob的DesignateServer注解定义了appIdParameterName属性,默认是appId;DesignateServerAspect拦截了@DesignateServer注解,它判断currentServer就是本机则执行point.proceed(),否则构建RemoteProcessReq,通过transportService.ask转发请求到指定server执行。

以上就是PowerJob的DesignateServer工作流程源码解读的详细内容,更多关于PowerJob DesignateServer的资料请关注脚本之家其它相关文章!

相关文章

  • Java设计模式中的观察者模式

    Java设计模式中的观察者模式

    观察者模式定义对象之间的一种一对多的依赖关系,使得每当一个对象的状态发生变化时,其相关的依赖对象都可以得到通知并被自动更新。主要用于多个不同的对象对一个对象的某个方法会做出不同的反应
    2023-02-02
  • 手把手教你使用Java实现在线生成pdf文档

    手把手教你使用Java实现在线生成pdf文档

    在实际的业务开发的时候,常常会需要把相关的数据信息,通过一些技术手段生成对应的PDF文件,然后返回给用户。本文将手把手教大家如何利用Java实现在线生成pdf文档,需要的可以参考一下
    2022-03-03
  • 如何使用axis调用WebService及Java WebService调用工具类

    如何使用axis调用WebService及Java WebService调用工具类

    Axis是一个基于Java的Web服务框架,可以用来调用Web服务接口,下面这篇文章主要给大家介绍了关于如何使用axis调用WebService及Java WebService调用工具类的相关资料,需要的朋友可以参考下
    2023-04-04
  • SpringMVC+Mybatis二维码实现多平台付款(附源码)

    SpringMVC+Mybatis二维码实现多平台付款(附源码)

    本文主要实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 关于国际化、OGNL表达式语言

    关于国际化、OGNL表达式语言

    本篇文章,小编为大家介绍关于国际化、OGNL表达式语言,有需要的朋友可以参考一下
    2013-04-04
  • Mybatis-Plus实现SQL拦截器的示例

    Mybatis-Plus实现SQL拦截器的示例

    这篇文章主要介绍了Mybatis-Plus实现一个SQL拦截器,通过使用SQL拦截器,开发人员可以在执行SQL语句之前或之后对其进行修改或记录,从而更好地控制和优化数据库操作,对Mybatis-Plus SQL拦截器相关知识感兴趣的朋友一起看看吧
    2023-05-05
  • MyBatis-Plus中公共字段的统一处理的实现

    MyBatis-Plus中公共字段的统一处理的实现

    在开发中经常遇到多个实体类有共同的属性字段,这些字段属于公共字段,本文主要介绍了MyBatis-Plus中公共字段的统一处理的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • SpringBoot+netty-socketio实现服务器端消息推送

    SpringBoot+netty-socketio实现服务器端消息推送

    这篇文章主要介绍了SpringBoot+netty-socketio实现服务器端消息推送,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Java中Iterator(迭代器)的用法详解

    Java中Iterator(迭代器)的用法详解

    Java迭代器(Iterator)是 Java 集合框架中的一种机制,它提供了一种在不暴露集合内部实现的情况下遍历集合元素的方法。本文主要介绍了它的使用方法,希望对大家有所帮助
    2023-05-05
  • springboot+mybatis plus实现树形结构查询

    springboot+mybatis plus实现树形结构查询

    实际开发过程中经常需要查询节点树,根据指定节点获取子节点列表,本文主要介绍了springboot+mybatis plus实现树形结构查询,感兴趣的可以了解一下
    2021-07-07

最新评论