【Apache ShenYu源码】看看贡献者如何实现支持提醒通知设计

简介: 在阅读中,还发现了有个html文件忘记加了开源协议,我们提下PR修复下,又收获了一次开源贡献!!PR提交戳这。

在这里插入图片描述

相信大家碰到源码时经常无从下手🙃,不知道从哪开始阅读,面对大量代码晕头转向,索性就读不下去了,又浪费了一次提升自己的机会😭。


我认为有一种方法,可以解决大家的困扰!那就是通过阅读某一次开源的【PR】,从这个入口出发去阅读源码!!


至此,我们发现自己开始从大量堆砌的源码中脱离开来😀,柳暗花明又一村。

一、前瞻

Ok,开始我们今天的PR阅读

在这里插入图片描述

翻译过来大致意思就是添加提醒通知的功能。翻译如下:

支持提醒通知设计

  • Shenyu admin 提供警报报告 API,/alert/report用于从网关 pulgin 接收警报内容
  • 网关在警报触发时发送警报消息
  • 神宇仪表板支持管理警报接收者名称,警报类型(电子邮件,钉钉,微信...)

我们可以思考下今天的阅读线索了

  1. 什么情况下会触发该警报信息
  2. 要支持多种警报类型,贡献者的代码是怎么设计成可扩展的

二、探索

话不多说,先整体看下本次PR的整体提交,从全局看下做了哪些修改。

在这里插入图片描述

还有很多提交没有截图下来,本次提交代码量可谓巨大了,那我们就先看看最核心的功能shenyu-alert模块

先思考下,既然是告警,核心接口就是发送告警接口,可以看到AlertNotifyHandler的send接口,我们就从这个入口开始探索,看看线索1的答案。

public interface AlertNotifyHandler {
   
   

    /**
     * send alert.
     *
     * @param receiver Notification configuration information
     * @param alert    Alarm information
     * @throws AlertNoticeException when send receiver error
     */
    void send(AlertReceiverDTO receiver, AlarmContent alert) throws AlertNoticeException;

    /**
     * alert type.
     *
     * @return type
     */
    byte type();
}

通过引用来查询,发现send()方法最终的调用者是通过Controller来触发告警,很奇怪,告警不是应该内部触发吗?

@RestApi("/alert/report")
public class AlertReportController {
   
   

    @Autowired
    private AlertDispatchService alertDispatchService;

    /**
     * report new alert content.
     *
     * @param alarmContent AlertContentDTO
     * @return row int
     */
    @PostMapping
    public ShenyuAdminResult reportAlert(@Valid @RequestBody final AlarmContent alarmContent) {
   
   
        alertDispatchService.dispatchAlert(alarmContent);
        return ShenyuAdminResult.success(ShenyuResultMessage.CREATE_SUCCESS);
    }

}

我们重新回顾下贡献者在PR写下的注释,有提到下面这一条:

Shenyu admin 提供警报报告 API,/alert/report用于从网关 pulgin 接收警报内容

也就是说告警是通过http请求触发,同时触发对象是网关的各个pulgin插件。

那我们再看看pulgin插件什么情况下会发送告警的http请求呢。

我们直接通过全局搜索/alert/report,看看哪些地方触发该http请求。

在这里插入图片描述

再找到对应执行的代码:

public class GlobalErrorHandler implements ErrorWebExceptionHandler {
   
   

    private static final Logger LOG = LoggerFactory.getLogger(GlobalErrorHandler.class);

    /**
     * handler error.
     *
     * @param exchange  the exchange
     * @param throwable the throwable
     * @return error result
     */
    @Override
    @NonNull
    public Mono<Void> handle(@NonNull final ServerWebExchange exchange, @NonNull final Throwable throwable) {
   
   
        LOG.error("handle error: {} formatError:{} throwable:", exchange.getLogPrefix(), formatError(throwable, exchange.getRequest()), throwable);
        HttpStatus httpStatus;
        Object errorResult;
        String errorMsg = "";
        if (throwable instanceof IllegalArgumentException) {
   
   
            httpStatus = HttpStatus.BAD_REQUEST;
            errorResult = ShenyuResultWrap.error(exchange, httpStatus.value(), throwable.getMessage(), null);
            errorMsg = throwable.getMessage();
        } else if (throwable instanceof ResponseStatusException) {
   
   
            httpStatus = ((ResponseStatusException) throwable).getStatus();
            String errMsg = StringUtils.hasLength(((ResponseStatusException) throwable).getReason()) ? ((ResponseStatusException) throwable).getReason() : httpStatus.getReasonPhrase();
            errorResult = ShenyuResultWrap.error(exchange, httpStatus.value(), errMsg, null);
            errorMsg = errMsg;
        } else {
   
   
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            errorResult = ShenyuResultWrap.error(exchange, httpStatus.value(), httpStatus.getReasonPhrase(), null);
            errorMsg = httpStatus.getReasonPhrase();
        }
        exchange.getResponse().setStatusCode(httpStatus);
        Map<String, String> labels = new HashMap<>(8);
        labels.put("global", "error");
        labels.put("component", "gateway");
        AlarmSender.alarmMediumCritical("ShenYu-Gateway-Global-Error", errorMsg, labels);
        return WebFluxResultUtils.result(exchange, errorResult);
    }

}

可以看到调用者实现了Spring的ErrorWebExceptionHandler类,也就是说这个警报的实际调用者是用Spring内置的web错误处理器

到这里我们就解决了我们的阅读线索1了。

什么情况下会触发该警报信息

还没完呢,我们继续阅读线索2的探索:要支持多种警报类型,贡献者的代码是怎么设计成可扩展的

既然要可扩展,肯定有底层接口在设定规则,我们找下这个底层接口。

在这里插入图片描述

这个底层接口其实还是我们上文提到的send接口,可以看到send方法的子类实现有钉钉、邮箱通知。

两个子类实现都是实现相同的底层接口AlertNotifyHandler,只要在配置上配置哪个通知实现,ShenYu alert模块便会实例化对应的通知实现,也就能达到可扩展的目的。

@Component
final class EmailAlertNotifyStrategy implements AlertNotifyHandler {
   
    }
@Component
final class EmailAlertNotifyStrategy implements AlertNotifyHandler {
   
    }

三、总结

在阅读中,还发现了有个html文件忘记加了开源协议,我们提下PR修复下,又收获了一次开源贡献!!

PR提交戳这。

在这里插入图片描述

未完待续。。。

好了,今天的分享就到这🤔。大家能否感受到通过PR这种方式来阅读源码的乐趣呢

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

相关文章
|
6月前
|
存储 缓存 负载均衡
【Apache ShenYu源码】如何实现负载均衡模块设计
整个模块为ShenYu提供了什么功能。我们可以看下上文我们提到的工厂对象。/***/核心方法很清晰,我们传入Upsteam列表,通过这个模块的负载均衡算法,负载均衡地返回其中一个对象。这也就是这个模块提供的功能。
|
6月前
|
Java
apache-incubator-streampark源码编译本地运行(七)
apache-incubator-streampark源码编译本地运行(七)
111 1
|
6月前
|
存储 SQL 关系型数据库
Apache Doris 聚合函数源码阅读与解析|源码解读系列
Apache Doris Active Contributor 隐形通过本文记录下对源码的理解,以方便新人快速上手源码开发。
Apache Doris 聚合函数源码阅读与解析|源码解读系列
|
6月前
|
Apache
Apache ZooKeeper - 构建ZooKeeper源码环境及StandAlone模式下的服务端和客户端启动
Apache ZooKeeper - 构建ZooKeeper源码环境及StandAlone模式下的服务端和客户端启动
126 2
|
6月前
|
SQL Java 数据库连接
Java【付诸实践 01】使用org.apache.ibatis.plugin.Interceptor拦截器实现全局mapper.xml参数注入(可用于切换数据库实例schema)源码实例分享
Java【付诸实践 01】使用org.apache.ibatis.plugin.Interceptor拦截器实现全局mapper.xml参数注入(可用于切换数据库实例schema)源码实例分享
146 0
|
6月前
apache-incubator-streampark源码编译本地运行(六)
apache-incubator-streampark源码编译本地运行(六)
89 0
|
11月前
apache-incubator-streampark源码编译本地运行(五)
apache-incubator-streampark源码编译本地运行(五)
73 0
|
11月前
|
Java Scala Maven
apache-incubator-streampark源码编译本地运行(四)
apache-incubator-streampark源码编译本地运行(四)
95 0
|
30天前
|
SQL Java API
Apache Flink 2.0-preview released
Apache Flink 社区正积极筹备 Flink 2.0 的发布,这是自 Flink 1.0 发布以来的首个重大更新。Flink 2.0 将引入多项激动人心的功能和改进,包括存算分离状态管理、物化表、批作业自适应执行等,同时也包含了一些不兼容的变更。目前提供的预览版旨在让用户提前尝试新功能并收集反馈,但不建议在生产环境中使用。
589 13
Apache Flink 2.0-preview released
|
1月前
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
68 3

推荐镜像

更多