首页 文章 精选 留言 我的

精选列表

搜索[网络监控],共10000篇文章
优秀的个人博客,低调大师

Elastalert-基于Elasticsearch层面的监控告警框架

打开微信扫一扫,关注微信公众号【数据与算法联盟】 转载请注明出处: http://blog.csdn.net/gamer_gyt 博主微博: http://weibo.com/234654758 Github: https://github.com/thinkgamer 写在前边的话 Elastalert是Yelp公司用python2.6写的一个报警框架,github地址为 https://github.com/Yelp/elastalert 环境介绍 Ubuntu16.04 Elasticsearch 2.4.1 Logstash 2.4.0 Kibana 4.6.1 Elastalert的安装 Elastalert的安装相对比较简单,只需要按照步骤走就没有问题 git clone https://github.com/Yelp/elastalert.git 进入elastalert的目录,执行 Pip install -r requirements.txt Python setup.py install OK 安装完事 安装之后会自带三个命令 elastalert-create-index:ElastAlert会把执行记录存放到一个ES 索引中,该命令就是用来 创建这个索引的,默认情况下,索引名叫elastalert_status。其中有4个 _type,都有 自己的@timestamp字段,所以同样也可以用kibana,来查看这个索引的日志记录情况。 elastalert-rule-from-kibana:从Kibana3已保存的仪表盘中读取Filtering设置,帮助生成config.yaml里的配置。不过注意,它只会读取filtering,不包括queries。 elastalert-test-rule:测试自定义配置中的rule设置。 Elastalert支持的警告类型 Command Email JIRA OpsGenie SNS HipChat Slack Telegram Debug 至于每种是干什么的,参考官网资料吧,不过多解释 http://elastalert.readthedocs.io/en/latest/ config.ymal中的配置项 Rules_folder:用来加载下一阶段rule的设置,默认是example_rules Run_every:用来设置定时向elasticsearch发送请求 Buffer_time:用来设置请求里时间字段的范围,默认是45分钟 Es_host:elasticsearch的host地址 Es_port:elasticsearch 对应的端口号 Use_ssl:可选的,选择是否用SSL连接es,true或者false Verify_certs:可选的,是否验证TLS证书,设置为true或者false,默认为true Es_username:es认证的username Es_password:es认证的password Es_url_prefix:可选的,es的url前缀(我的理解是https或者http) Es_send_get_body_as:可选的,查询es的方式,默认的是GET Writeback_index:elastalert产生的日志在elasticsearch中的创建的索引 Alert_time_limit:失败重试的时间限制 Elastalert的rule规则 name:配置,每个rule需要有自己独立的name,一旦重复,进程将无法启动。 type:配置,选择某一种数据验证方式。 index:配置,从某类索引里读取数据,目前已经支持Ymd格式,需要先设置 use_strftime_index:true,然后匹配索引,配置形如:index: logstash-es-test%Y.%m.%d,表示匹配logstash-es-test名称开头,以年月日作为索引后缀的index。 filter:配置,设置向ES请求的过滤条件。 timeframe:配置,累积触发报警的时长。 alert:配置,设置触发报警时执行哪些报警手段。不同的type还有自己独特的配置选项。目前ElastAlert 有以下几种自带ruletype: any:只要有匹配就报警; blacklist:compare_key字段的内容匹配上 blacklist数组里任意内容; whitelist:compare_key字段的内容一个都没能匹配上whitelist数组里内容; change:在相同query_key条件下,compare_key字段的内容,在 timeframe范围内 发送变化; frequency:在相同 query_key条件下,timeframe 范围内有num_events个被过滤出 来的异常; spike:在相同query_key条件下,前后两个timeframe范围内数据量相差比例超过spike_height。其中可以通过spike_type设置具体涨跌方向是up,down,both 。还可以通过threshold_ref设置要求上一个周期数据量的下限,threshold_cur设置要求当前周期数据量的下限,如果数据量不到下限,也不触发; flatline:timeframe 范围内,数据量小于threshold 阈值; new_term:fields字段新出现之前terms_window_size(默认30天)范围内最多的terms_size (默认50)个结果以外的数据; cardinality:在相同 query_key条件下,timeframe范围内cardinality_field的值超过 max_cardinality 或者低于min_cardinality 一个小demo 这里我们还是测试rrsyslog发送日志的这个例子,就是启动ELK服务,rsyslog通过logstash把日志发送给elasticsearch,然后传送给kibana,logstash编写rsyslog_test.conf文件,内容为 input { tcp{ port => 5000 type => syslog } udp{ port => 5000 type => syslog } } output { stdout { codec=> rubydebug } elasticsearch { hosts => ["192.168.1.198:9200"] } } 然后启动ELK服务和rsyslog_test.conf文件 编辑elastalert下的configure.yaml文件 rules_folder: example_rules run_every: minutes: 1 buffer_time: minutes: 15 es_host: localhost es_port: 9200 writeback_index: elastalert_status alert_time_limit: days: 2 编辑example_rules/example_frequency.yaml 文件内容如下: es_host: localhost es_port: 9200 name: Example rule use_strftine_index: true type: frequency index: logstash-* num_events: 5 timeframe: hours: 1 filter: - term: _type: "syslog" alert: - "email" email: - "elastalert@example.com" 上边我们设置的事件次数是5,也就是说elaticseach记录的事件条件超过即发送email文件,这里的email文件我并没有配置,原因是测试没有成功,需要提供密码验证,没有解决,以后解决的话会在评论中给出,不过这里用debug替换下列verbose即可将邮件内容打印在窗口 启动elastalert服务,监听elasticsearch python -m elastalert.elastalert –debug –rule example_rules/example_frequency.yaml 这个时候我们的ELK已经启动了,再次启动终端,执行ssh localhost进行测试,只要在一分钟内连续输入几次的错误密码,这个时候就会在elastalert的终端看到类似下面这样的提示: INFO:elastalert:Queried rule Example rule from 2016-10-24 08:20 PDT to 2016-10-24 08:35 PDT: 34 / 34 hits INFO:elastalert:Skipping writing to ES: {'rule_name': 'Example rule', '@timestamp': '2016-10-24T15:35:00.120937Z', 'exponent': 0, 'until': '2016-10-24T15:36:00.120924Z'} INFO:elastalert:Alert for Example rule at 2016-10-24T15:34:24.422Z: INFO:elastalert:Example rule At least 5 events occurred between 2016-10-24 07:34 PDT and 2016-10-24 08:34 PDT @timestamp: 2016-10-24T15:34:24.422Z @version: 1 _id: AVf3VBTs1Cgl8RD3WDw9 _index: logstash-2016.10.24 _type: syslog host: 127.0.0.1 message: <38>Oct 24 08:34:24 ubuntu sshd[3097]: Connection closed by 127.0.0.1 port 52434 [preauth] type: syslog INFO:elastalert:Skipping writing to ES: {'hits': 34, 'matches': 1, '@timestamp': '2016-10-24T15:35:00.123939Z', 'rule_name': 'Example rule', 'starttime': '2016-10-24T15:20:00.031300Z', 'endtime': '2016-10-24T15:35:00.031300Z', 'time_taken': 0.09257292747497559} 说明整个告警体系已经OK了 邮件告警配置 上次在配置邮件告警时并没有取得成功,后来又尝试了几次,ok了 以下进行得操作基于上边得demo步骤 首先添加发送方: 在elastalert目录下编辑smtp_auth_file.yaml文件,加入你要使用发送邮件的账号和密码 这里我使用的是网易的163邮箱,这里的密码是你开启邮箱的POP3的客户端登陆密码,不是网页登陆邮箱的密码 user: "thinkgamer@163.com" password: "xxxxxxxx" 然后编辑你的配置文件,我这里使用 example_rules/example_frequency.yaml 别的配置正常配置,在alert之前加入 #SMTP协议的邮件服务器相关配置(我这里是腾讯企业邮箱) #smtp.163.com是网易163邮箱的smtp服务器 smtp_host: smtp.163.com smtp_port: 25 #用户认证文件,需要user和password两个属性 # smtp_auth_file.yaml,为刚才编辑的配置文件 smtp_auth_file: smtp_auth_file.yaml email_reply_to: thinkgamer@163.com from_addr: thinkgamer@163.com 修改email为你要接受邮件的邮箱 然后启动配置文件 python -m elastalert.elastalert --verbose --rule example_rules/example_frequency.yaml 测试: 查看邮件: Over!

优秀的个人博客,低调大师

源码分析Dubbo网络通讯篇之NettyServer网络事件之线程池

本文主要分析Dubbo线程池的构建过程,主要介绍官方文档中有关于ThreadPool的种类: fixed 固定大小线程池,启动时建立线程,不关闭,一致持有。(缺省) cached :缓存线程池,空闲一分钟,线程会消费,需要时重新创建新线程。 limited :可伸缩线程池,但池中的线程数只会增长不会收缩。 eager :优先使用线程来执行新提交任务。(渴望立即执行,而不是进入队列排队执行)。配置标签:< dubbo:protocol threadpool = "fixed" ../> 各种类型的线程池,内部就是根据规则创建不同的ThreadPoolExecutor对象,那我们先简单回顾一下线程池的基本知识,其构造方法如下所示: public ThreadPoolExecutor( int corePoolSize, // 线程池核心线程数、常驻线程数。 int maximumPoolSize, // 线程池中最大线程数量 long keepAliveTime, // 线程保持活跃时间,(如果线程创建,并空闲 //指定值后,线程会被回收,0表示不开启该特性,其范围针对 // corePoolSize的线程) TimeUnit unit, // keepAliveTime的时间单位。 BlockingQueue&lt; Runnable&gt; workQueue,// 任务队列 ThreadFactory threadFactory, // 线程工厂类,一般通过该线程工厂,为线程命名,以便区分线程。 RejectedExecutionHandler handler) // 拒绝策略。 提交任务流程(线程创建流程) 如果线程池中线程数量小于corePoolSize,则创建一个线程来执行该任务。 如果线程池中的线程大于等于corePoolSize,则尝试将任务放入队列中。 如果成功将任务放入队列,则本次提交任务正常结束,如果放入任务队列失败则继续下一步。 如果线程池中的线程数量小于最大线程数,则创建先的线程,否则执行拒绝策略。 更多有关线程池,请参考作者的另外一篇博文:源码分析JDK线程池 1、fixed 固定大小线程池 public class FixedThreadPool implements ThreadPool { @Override public Executor getExecutor(URL url) { String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME); int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS); int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES); return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, queues == 0 ? new SynchronousQueue<runnable>() : (queues &lt; 0 ? new LinkedBlockingQueue<runnable>() : new LinkedBlockingQueue<runnable>(queues)), new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url)); } } 实现要点: 首先获取可配置参数threadname、threads、queues三个参数,分别代表线程池中线程名前缀、线程中最大线程数量、任务队列长度。 要实现fixed固定大小线程池,故名思议,就是线程池自创建以来,线程数量始终保持一致。其实现要点是,corePoolSize、maximumPoolSize相等,并且其值等于threads(默认200),并且keepAliveTime=0,表示线程始终活跃。 任务队列,如果queues 为0,则使用SynchronousQueue,如果小于0,则使用无界队列,如果大于0,则创建容量为LinkedBlockingQueue的队列,超过容量,则拒绝入队。 线程工厂,NamedThreadFactory,主要设置线程名称,默认为Dubbo-thread-序号。 拒绝策略AbortPolicyWithReport,其主要是如果拒绝任务,首先会打印出详细日志,包含线程池的核心参数,并且会dump jstack 日志,日志文件默认存储在 user.home/Dubbo_JStack.log.timestamp,可以通过 dump.directory 属性配置,可通过< dubbo:protocol> < dubbo:parameter key =“” value = ""/> < /dubbo:protocol>。 >这里再简单介绍如果队列长度为0(默认),为什么是选用SynchronousQueue队列。 SynchronousQueue的一个简单理解:调用offer、put之前,必须先调用take,也就是先调用take方法的线程阻塞,然后当别的线程调用offer之后,调用take的线程被唤醒,如果没有线程调用take方法,一个线程调用offer方法,则会返回false,并不会将元素添加到SynchronousQueue队列中,因为SynchronousQueue内部的队列长度为0。 与该线程池相关的配置属性:threadname、theadpool、threads、queues。 2、cached 缓存线程池,线程空闲后会被回收 public class CachedThreadPool implements ThreadPool { @Override public Executor getExecutor(URL url) { String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME); int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS); int threads = url.getParameter(Constants.THREADS_KEY, Integer.MAX_VALUE); int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES); int alive = url.getParameter(Constants.ALIVE_KEY, Constants.DEFAULT_ALIVE); return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS, queues == 0 ? new SynchronousQueue<runnable>() : (queues &lt; 0 ? new LinkedBlockingQueue<runnable>() : new LinkedBlockingQueue<runnable>(queues)), new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url)); } } 实现要点:既然要实现线程可以被回收,则必然要设置 keepAliveTime。 故对应线程池核心参数设置,对应如下: corePoolSize:通过参数corethreads设置,默认为0 maximumPoolSize:通过参数threads设置,默认200 keepAliveTime:通过参数alive设置,默认为60 * 1000 workQueue :通过queues参数设置,默认为0 其他与fixed相同,则不重复介绍 3、limited 可伸缩线程池,其特征:线程数只增不减 public class LimitedThreadPool implements ThreadPool { @Override public Executor getExecutor(URL url) { String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME); int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS); int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS); int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES); return new ThreadPoolExecutor(cores, threads, Long.MAX_VALUE, TimeUnit.MILLISECONDS, queues == 0 ? new SynchronousQueue<runnable>() : (queues &lt; 0 ? new LinkedBlockingQueue<runnable>() : new LinkedBlockingQueue<runnable>(queues)), new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url)); } } 就不回收,与cached不同的就是 keepAliveTime 的取值不同,limited 取值为:Long.MAX_VALUE,其他与 cached 相同。 4、eager 其核心实现主要由 TaskQueue、EagerThreadPoolExecutor 共同完成。 首先,我们关注一下 TaskQueued 的 offer方法。 public boolean offer(Runnable runnable) { if (executor == null) { throw new RejectedExecutionException("The task queue does not have executor!"); } int currentPoolThreadSize = executor.getPoolSize(); // [@1](https://my.oschina.net/u/1198) // have free worker. put task into queue to let the worker deal with task. if (executor.getSubmittedTaskCount() &lt; currentPoolThreadSize) { // @2 return super.offer(runnable); } // return false to let executor create new worker. if (currentPoolThreadSize &lt; executor.getMaximumPoolSize()) { // [@3](https://my.oschina.net/u/2648711) return false; } // currentPoolThreadSize &gt;= max // @4 return super.offer(runnable); } 代码@1:获取当前线程池中线程的数量。 代码@2:如果当前已提交到线程池中的任务数量小于当前存在在的线程数,则走默认的提交流程。 代码@3:如果当前已提交到线程中的数量大于当前的线程池,并线程池中数量并未达到线程池允许创建的最大线程数时,则返回false,并不入队,其效果是会创建新的线程来执行。 代码@4:如果当前线程池中的线程已达到允许创建的最大线程数后,走默认的提交任务逻辑。 EagerThreadPoolExecutor#execute public void execute(Runnable command) { if (command == null) { throw new NullPointerException(); } // do not increment in method beforeExecute! submittedTaskCount.incrementAndGet(); // @1 try { super.execute(command); } catch (RejectedExecutionException rx) { // retry to offer the task into queue. final TaskQueue queue = (TaskQueue) super.getQueue(); try { if (!queue.retryOffer(command, 0, TimeUnit.MILLISECONDS)) { submittedTaskCount.decrementAndGet(); throw new RejectedExecutionException("Queue capacity is full."); } } catch (InterruptedException x) { submittedTaskCount.decrementAndGet(); throw new RejectedExecutionException(x); } } catch (Throwable t) { // decrease any way submittedTaskCount.decrementAndGet(); // @2 } } 其核心实现逻辑:如果提交任务失败,则再走一次默认的任务提交流程。 最总后结一下Eager的核心特性。 public class EagerThreadPool implements ThreadPool { @Override public Executor getExecutor(URL url) { String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME); int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS); int threads = url.getParameter(Constants.THREADS_KEY, Integer.MAX_VALUE); int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES); int alive = url.getParameter(Constants.ALIVE_KEY, Constants.DEFAULT_ALIVE); // init queue and executor TaskQueue<runnable> taskQueue = new TaskQueue<runnable>(queues &lt;= 0 ? 1 : queues); EagerThreadPoolExecutor executor = new EagerThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS, taskQueue, new NamedThreadFactory(name, true), new AbortPolicyWithReport(name, url)); taskQueue.setExecutor(executor); return executor; } } 其核心特性如下: 首先,其配置参数与cached类型的线程池相同,说明eager也是基于缓存的。 eager与cached类型线程池不同的一点是,提交任务后,线程优先于队列,默认的提交流程是如果线程数达到核心线程数后,新提交的任务是首先进入队列,但eager是优先创建线程来执行,这有点与公平锁,非公平锁一样的概念了。 >作者介绍:丁威,《RocketMQ技术内幕》作者,RocketMQ 社区优秀布道师、CSDN2019博客之星TOP10,维护公众号:中间件兴趣圈目前已陆续发表源码分析Java集合、Java 并发包(JUC)、Netty、Mycat、Dubbo、RocketMQ、Mybatis等源码专栏。可以点击链接加入中间件知识星球 ,一起探讨高并发、分布式服务架构,交流源码。 </runnable></runnable></runnable></runnable></runnable></runnable></runnable></runnable></runnable></runnable></runnable>

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册