解释器模式

解释器模式

  • 解释器模式定义
    • 使用场景
    • 角色定义
      • 1. AbstractExpression--抽象解释器:
      • 2. TerminalExpression-终结符表达式:
      • 3. NonterminalExpression-一非终结符表达式:
      • 4. Context-环境角色:
    • 需求背景
      • 1. 首先设置一个告警规则
      • 2. 定义五种告警的判断规则
      • 3. 具体代码
        • 3.1 抽象告警规则接口
        • 3.2 具体告警规则实现
        • 3.3 告警规则解释器
        • 3.4 测试案例
        • 3.5 测试结果

解释器模式定义

给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子

使用场景

  1. 重复发生的问题可以使用解释器模式
  2. 一个简单语法需要解释的场景

角色定义

1. AbstractExpression–抽象解释器:

具体的解释任务由各个实现类完成,具体的解释器分别由 TerminalExpression 和 Non-terminalExpression 完成。

2. TerminalExpression-终结符表达式:

实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。

3. NonterminalExpression-一非终结符表达式:

文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。

4. Context-环境角色:

一般是用来存放文法中各个终结符所对应的具体值这些信息需要存放到环境角色中,很多情况下我们使用 Map 来充当环境角色就足够了。

需求背景

模拟监控业务系统的运行情况,及时将异常报告发送给开发者,比如,如果每分钟接口出错数超过100,监控系统就通过短信、微信、邮件等方式发送告警给开发者

下面是一个简单的Java示例代码:

1. 首先设置一个告警规则

每分钟API总错数超过100或者每分钟API总调用数超过10000就触发告警

api_error_per_minute > 100 || api_count_per_minute > 10000

2. 定义五种告警的判断规则

||、&&、<、>、==,其中<、>、==运算符的优先级高于||和&&

3. 具体代码

3.1 抽象告警规则接口

public interface Expression {

    boolean interpret(Map<String, Long> stats);
}

3.2 具体告警规则实现

public class OrExpression implements Expression {

    private List<Expression> expressions = new ArrayList<>();

    public OrExpression(List<Expression> expressions) {
        this.expressions.addAll(expressions);
    }

    public OrExpression(String strOrExpression) {
        String[] andExpressions = strOrExpression.split("\\|\\|");
        for (String andExpression : andExpressions) {
            expressions.add(new AndExpression(andExpression));
        }
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        for (Expression expression : expressions) {
            if (expression.interpret(stats)) {
                return true;
            }
        }
        return false;
    }
}
public class AndExpression implements Expression {

    private List<Expression> expressions = new ArrayList<>();

    public AndExpression(List<Expression> expressions) {
        this.expressions.addAll(expressions);
    }

    public AndExpression(String strAndExpression) {
        String[] strExpressions = strAndExpression.split("&&");
        for (String strExpression : strExpressions) {
            if (strExpression.contains(">")) {
                expressions.add(new GreaterExpression(strExpression));
            } else if (strExpression.contains("<")) {
                expressions.add(new LesserExpression(strExpression));
            } else if (strAndExpression.contains("==")) {
                expressions.add(new EqualExpression(strExpression));
            } else {
                throw new RuntimeException("Expression is invalid: " + strAndExpression);
            }
        }
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        for (Expression expression : expressions) {
            if (!expression.interpret(stats)) {
                return false;
            }
        }
        return true;
    }
}
public class EqualExpression implements Expression {

    private String key;
    private Long value;

    public EqualExpression(String key, Long value) {
        this.key = key;
        this.value = value;
    }

    public EqualExpression(String strExpression) {
        String[] elements = strExpression.trim().split("\\s+");
        if (elements.length != 3 || !elements[1].trim().equals("==")) {
            throw new RuntimeException("Expression is invalid: " + strExpression);
        }
        this.key = elements[0].trim();
        this.value = Long.parseLong(elements[2].trim());
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        if (!stats.containsKey(key)) {
            return false;
        }
        Long statsValue = stats.get(key);
        return statsValue == value;
    }
}
public class GreaterExpression implements Expression {

    private String key;
    private long value;

    public GreaterExpression(String key, long value) {
        this.key = key;
        this.value = value;
    }

    public GreaterExpression(String strExpression) {
        String[] elements = strExpression.trim().split("\\s+");
        if (elements.length != 3 || !elements[1].trim().equals(">")) {
            throw new RuntimeException("Expression is invalid: " + strExpression);
        }
        this.key = elements[0].trim();
        this.value = Long.parseLong(elements[2].trim());
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        if (!stats.containsKey(key)) {
            return false;
        }
        Long statValue = stats.get(key);
        return statValue > value;
    }
}
public class LesserExpression implements Expression {

    private String key;
    private long value;

    public LesserExpression(String key, long value) {
        this.key = key;
        this.value = value;
    }

    public LesserExpression(String strExpression) {
        String[] elements = strExpression.trim().split("\\s+");
        if (elements.length != 3 || !elements[1].trim().equals("<")) {
            throw new RuntimeException("Expression is invalid: " + strExpression);
        }
        this.key = elements[0].trim();
        this.value = Long.parseLong(elements[2].trim());
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        if (!stats.containsKey(key)) {
            return false;
        }
        Long statsValue = stats.get(key);
        return statsValue < value;
    }
}

3.3 告警规则解释器

public class AlertRuleInterpreter {

    private Expression expression;

    public AlertRuleInterpreter(String ruleExpression) {
        this.expression = new OrExpression(ruleExpression);
    }

    public boolean interpret(Map<String, Long> stats) {
        return expression.interpret(stats);
    }
}

3.4 测试案例

    @Test
    public void test() {
        String rule = "api_error_per_minute > 100 || api_count_per_minute > 10000";
        AlertRuleInterpreter alertRuleInterpreter = new AlertRuleInterpreter(rule);
        HashMap<String, Long> statsMap = new HashMap<>();
        statsMap.put("api_error_per_minute", 99l);
        statsMap.put("api_count_per_minute", 121l);
        boolean alertInterpret = alertRuleInterpreter.interpret(statsMap);
        String alert = alertInterpret == true ? "超过阈值,危险!!" : "目前运行良好";
        log.info("预警结果为:alert:{}", alert);
    }

3.5 测试结果

预警结果为:alert:目前运行良好

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/17514.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka上的优化经验

1. 平滑扩容 Motivation kafka扩容⼀台新机器的流程 假如集群有 3 个 broker &#xff0c;⼀共有 4 个 TP &#xff0c;每个 3 副本&#xff0c;均匀分布。现在要扩容⼀台机器&#xff0c; 新 broker 加⼊集群后需要通过⼯具进⾏ TP 的迁移。⼀共迁移 3 个 TP 的副…

Spring Boot集成ShardingSphere实现按月数据分片及创建自定义分片算法 | Spring Cloud 44

一、前言 在前面我们通过以下章节对数据分片有了基础的了解&#xff1a; Spring Boot集成ShardingSphere实现数据分片&#xff08;一&#xff09; | Spring Cloud 40 Spring Boot集成ShardingSphere实现数据分片&#xff08;二&#xff09; | Spring Cloud 41 Spring Boot集…

权限提升:信息收集 .(Linux系统)

权限提升&#xff1a;信息收集. 权限提升简称提权&#xff0c;由于操作系统都是多用户操作系统&#xff0c;用户之间都有权限控制&#xff0c;比如通过 Web 漏洞拿到的是 Web 进程的权限&#xff0c;往往 Web 服务都是以一个权限很低的账号启动的&#xff0c;因此通过 Webshel…

1.1 基于B/S 结构的 Web 应用

文章目录 1.1 基于B/S 结构的 Web 应用1.2 JDK安装与配置1.3 服务器Tomcat下载与安装1.4 Eclipse安装与使用1.4.1 Eclipse 下载及创建Dynamic Web Project1.4.2 Eclipse 中的编码问题1.4.3 将Tomcat和Eclipse相关联1.4.4 Eclipse 自动部署项目到 Tomcat 的 webapps 目录 1.5 My…

【AWS入门】AWS Lamda

目录 创建一个Lamda函数用Lamda函数控制启停EC2实例创建一台EC2实例创建角色创建lamda函数 使用Amazon EventBridge计划启停实例创建EventBridge 用户往S3存储桶上传图片文件&#xff0c;触发Lambda函数&#xff0c;将图片压缩并上传至另一个存储桶创建两个存储桶通过Cloudform…

【SpringMVC】| SpringMVC执行流程原理 | 常用注解 剥析

MVC目录 一. &#x1f981; MVC模型二. &#x1f981; SpringMVC1. SpringMVC执行流程&#xff08;重点&#xff09;Ⅰ. SpringMVC四大组件Ⅱ. 执行流程 2. RequestMapping3. RequestParam4. ReuqestHeader & CookieValue5. RESTful风格支持Ⅰ. 传统 vs restfulⅡ. PathVar…

【网络技术】什么是CNI

序言 你只管努力&#xff0c;其他交给时间&#xff0c;时间会证明一切。 Never look back unless you are planning to go that way. 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用…

【应急响应】日志自动提取分析项目ELKLogkitLogonTracerAnolog等

日志自动提取-七牛Logkit&观星应急工具 1、七牛Logkit&#xff1a;(Windows&Linux&Mac等) https://github.com/qiniu/logkit/ 支持的数据源&#xff08;各类日志&#xff0c;各个系统&#xff0c;各个应用等&#xff09; File: 读取文件中的日志数据&#xff0c;包…

面了一个4年经验的测试工程师,自动化都不会也要15k,我也是醉了····

在深圳这家金融公司也待了几年&#xff0c;被别人面试过也面试过别人&#xff0c;大大小小的事情也见识不少&#xff0c;今天又是团面的一天&#xff0c; 一百多个人都聚集在一起&#xff0c;因为公司最近在谈项目出来面试就2个人&#xff0c;无奈又被叫到面试房间。 整个过程…

数说热点 | 跟着《长月烬明》起飞,今年各地文旅主打的就是一个听劝

近日&#xff0c;随着热播剧《长月烬明》的爆火&#xff0c;蚌埠、宣城、敦煌等多个与剧情梦幻联动的宝藏城市被带飞&#xff0c;各地热心网友也纷纷催促自家文旅局赶紧“蹭飞”&#xff0c;《长月烬明》以一己之力打造了影视文旅融合的新样板。 仙偶剧特效天花板&#xff0c;…

《互联网安全产品漏洞管理规定》

《网络产品安全漏洞管理规定》由工业和信息化部、国家互联网信息办公室、公安部联合印发&#xff0c;自2021年9月1日起施行。 该《规定》明确&#xff0c;任何组织或者个人不得利用网络产品安全漏洞从事危害网络安全的活动&#xff0c;不得非法收集、出售、发布网络产品安全漏洞…

Redis高频面试题,使用场景

一、缓存 1、什么是缓存穿透 ? 怎么解决 ? 缓存穿透 查询一个不存在的数据&#xff0c;mysql查询不到数据也不会直接写入缓存&#xff0c;就会导致每次请求都查数据库。 解决 方案一&#xff1a;缓存空数据&#xff0c;查询返回的数据为空&#xff0c;仍把这个空结果进行…

【JavaEE】认识线程

目录 1、什么是线程 2、为什么引入线程 2.1、线程的优缺点 3、CPU的工作原理 4、线程和进程的关系 4.1、线程和进程的入口函数 4.2、线程独享的资源 1、什么是线程 一个进程中可以有一个或者多个线程&#xff0c;每个线程都是一个独立的执行流。多个线程之间&#xff0c;也…

3.rabbitMQ之发布确认高级和整合springboot(重要)找了很多博客整理出来的

1.极端情况下 rabbitMQ需要重启,导致消息投递失败(生产者发消息全部丢失)(交换机或者队列出问题) 生产者需要把数据放到缓存,用定时任务重新发送 解决方法: 0.必须配置文件写 spring.rabbitmq.publisher-confirm-typecorrelatedspring.rabbitmq.publisher-returnstruecorrelati…

Word Embedding

One-hot-encoding 缺点 1.向量维度和向量个数很大&#xff0c;假设有1w个token的话&#xff0c;向量个数和维度就都是1w 2. 语义相近的词的向量并不相似 Word Embedding 核心思想&#xff1a;可以通过上下文理解单词的语义 predection-based方法 使用前一个单词预测下一个…

【机器学习】信息量、香农熵、信息增益

这节可以搭配 【机器学习】Logistic回归&#xff08;重新整理&#xff09;信息量&#xff08;信息&#xff09;信息量公式的推理过程 香农熵信息增益 【机器学习】Logistic回归&#xff08;重新整理&#xff09; B站视频&#xff1a;“交叉熵”如何做损失函数&#xff1f;打包…

Linux一学就会——编写自己的shell

编写自己的shell 进程程序替换 替换原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数 以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行…

视觉震撼的数据可视化示例

众所周知&#xff0c;数据可以非常强大——当你真正理解它告诉你什么时。 数据和信息可视化(数据可视化或信息可视化)是对大量复杂的定量、定性数据、信息进行设计和创建易于沟通、易于理解的图形或视觉表示的实践&#xff0c;在静态、动态或交互式视觉项目的帮助下&#xff0…

存储网络架构——DAS、NAS、SAN、分布式组网架构

目录 DAS直连式存储 NAS网络附加存储 SAN存储 存储区域网络 分布式存储组网 DAS直连式存储 DAS遇到的挑战 NAS网络附加存储 向主机提供文件服务&#xff1b;文件系统由存储设备维护&#xff0c;用户访问文件系统&#xff0c;不直接访问底层存储 拥有所有主机上文件与底层存储空…

JS案例分析-某国际音x-tt-params参数分析

今天我们要分析的网站是&#xff1a;https://www.tiktok.com/selenagomez?langen&#xff0c;参数名字叫x-tt-params。 先来抓个包 这个接口是用户视频列表url&#xff0c;参数叫x-tt-params&#xff0c;该接口中还有其他参数像msToken&#xff0c;X-Bogus&#xff0c; _sig…
最新文章