fyzn12
RSS SITEMAP

Articles

  • FileBeat

    一、 filebeat简单理解 1.1、filebeat和beats的关系 首先filebeat是Beats中的一员。 Beats在是一个轻量级日志采集器,其实Beats家族有6个成员,早期的ELK架构中使用Logstash收集、解析日志,但是Logstash对内存、cpu、io等资源消耗比较高。相比Logstash,Beats所占系统的CPU和内存几乎可以忽略不计。 目前Beats包含六种工具: Packetbeat:网络数据(收集网络流量数据) Metricbeat:指标(收集系统、进程和文件系统级别的CPU和内存使用情况等数据) Filebeat:日志文件(收集文件数据) Winlogbeat:windows事件日志(收集Windows事件日志数据) Auditbeat:审计数据(收集审计日志) Heartbeat:运行时间监控(收集系统运行时的数据) 1.2、filebeat是什么  Filebeat是用于转发和集中日志数据的轻量级传送工具。Filebeat监视您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash进行索引。  Filebeat的工作方式如下:启动Filebeat时,它将启动一个或多个输入,这些输入将在为日志数据指定的位置中查找。对于Filebeat所找到的每个日志,Filebeat都会启动收集器。每个收集器都读取单个日志以获取新内容,并将新日志数据发送到libbeat,libbeat将聚集事件,并将聚集的数据发送到为Filebeat配置的输出。 1.3、filebeat和logstash的关系  因为logstash是jvm跑的,资源消耗比较大,所以后来作者又用golang写了一个功能较少但是资源消耗也小的轻量级的logstash-forwarder。不过作者只是一个人,加入http://elastic.co公司以后,因为es公司本身还收购了另一个开源项目packetbeat,而这个项目专门就是用golang的,有整个团队,所以es公司干脆把logstash-forwarder的开发工作也合并到同一个golang团队来搞,于是新的项目就叫filebeat了。 二、filebeat原理是什么 2.1、filebeat的构成  filebeat结构:由两个组件构成,分别是inputs(输入)和harvesters(收集器),这些组件一起工作来跟踪文件并将事件数据发送到您指定的输出,harvester负责读取单个文件的内容。harvester逐行读取每个文件,并将内容发送到输出。为每个文件启动一个harvester。harvester负责打开和关闭文件,这意味着文件描述符在harvester运行时保持打开状态。如果在收集文件时删除或重命名文件,Filebeat将继续读取该文件。这样做的副作用是,磁盘上的空间一直保留到harvester关闭。默认情况下,Filebeat保持文件打开,直到达到close_inactive 关闭harvester可以会产生的结果: 文件处理程序关闭,如果harvester仍在读取文件时被删除,则释放底层资源。 只有在scan_frequency结束之后,才会再次启动文件的收集。 如果该文件在harvester关闭时被移动或删除,该文件的收集将不会继续  一个input负责管理harvesters和寻找所有来源读取。如果input类型是log,则input将查找驱动器上与定义的路径匹配的所有文件,并为每个文件启动一个harvester。每个input在它自己的Go进程中运行,Filebeat当前支持多种输入类型。每个输入类型可以定义多次。日志输入检查每个文件,以查看是否需要启动harvester、是否已经在运行harvester或是否可以忽略该文件 2.2、filebeat如何保存文件的状态 Filebeat保留每个文件的状态,并经常将状态刷新到磁盘中的注册表文件中。该状态用于记住harvester读取的最后一个偏移量,并确保发送所有日志行。如果无法访问输出(如Elasticsearch或Logstash),Filebeat将跟踪最后发送的行,并在输出再次可用时继续读取文件。当Filebeat运行时,每个输入的状态信息也保存在内存中。当Filebeat重新启动时,来自注册表文件的数据用于重建状态,Filebeat在最后一个已知位置继续每个harvester。对于每个输入,Filebeat都会保留它找到的每个文件的状态。由于文件可以重命名或移动,文件名和路径不足以标识文件。对于每个文件,Filebeat存储唯一的标识符,以检测文件是否以前被捕获。 2.3、filebeat何如保证至少一次数据消费  Filebeat保证事件将至少传递到配置的输出一次,并且不会丢失数据。是因为它将每个事件的传递状态存储在注册表文件中。在已定义的输出被阻止且未确认所有事件的情况下,Filebeat将继续尝试发送事件,直到输出确认已接收到事件为止。如果Filebeat在发送事件的过程中关闭,它不会等待输出确认所有事件后再关闭。当Filebeat重新启动时,将再次将Filebeat关闭前未确认的所有事件发送到输出。这样可以确保每个事件至少发送一次,但最终可能会有重复的事件发送到输出。通过设置shutdown_timeout选项,可以将Filebeat配置为在关机前等待特定时间。 本文来源于: FileBeat
  • GC和JVM

    GC和JVM Tuning 作者:马士兵教育 http://mashibing.com GC的基础知识 1.什么是垃圾 C语言申请内存:malloc free C++: new delete c/C++ 手动回收内存 Java: new ? 自动内存回收,编程上简单,系统不容易出错,手动释放内存,容易出两种类型的问题: 忘记回收 多次回收 没有任何引用指向的一个对象或者多个对象(循环引用) 2.如何定位垃圾 引用计数(ReferenceCount) 根可达算法(RootSearching) 3.常见的垃圾回收算法 标记清除(mark sweep) - 位置不连续 产生碎片 效率偏低(两遍扫描) 拷贝算法 (copying) - 没有碎片,浪费空间 标记压缩(mark compact) - 没有碎片,效率偏低(两遍扫描,指针需要调整) 4.JVM内存分代模型(用于分代垃圾回收算法) 部分垃圾回收器使用的模型 除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型 G1是逻辑分代,物理不分代 除此之外不仅逻辑分代,而且物理分代 新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace 永久代 元数据 - Class 永久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存) 字符串常量 1.
  • Redis结合kafka实现高并发抢单

    实现环境:kafka、redis、mysql8 使用Spring Boot搭建环境,数据库采用乐观锁 缓存和数据一致性分析 缓存和 DB 的一致性是一个讨论很多的问题,推荐看参考中的 使用缓存的正确姿势,首先看下先更新数据库,再更新缓存策略, 假设 A、B 两个线程,A 成功更新数据,在要更新缓存时,A 的时间片用完了,B 更新了数据库接着更新了缓存,这是 CPU 再分配给 A,则 A 又更新了缓存,这种情况下缓存中就是脏数据. 那么,如果避免这个问题呢?就是缓存不做更新,仅做删除,先更新数据库再删除缓存。 对于上面的问题,A 更新了数据库,还没来得及删除缓存,B 又更新了数据库,接着删除了缓存,然后 A 删除了缓存, 这样只有下次缓存未命中时,才会从数据库中重建缓存,避免了脏数据。 但是,也会有极端情况出现脏数据, A 做查询操作,没有命中缓存,从数据库中查询,但是还没来得及更新缓存,B 就更新了数据库,接着删除了缓存,然后 A 又重建了缓存,这时 A 中的就是脏数据,但是这种极端情况需要数据库的写操作前进入数据库,又晚于写操作删除缓存来更新缓存,发生的概率极其小,不过为了避免这种情况,可以为缓存设置过期时间。 高并发控制实现 1.Redis的限流控制 根据前面的优化分析,假设现在有 10 个商品,有 1000 个并发秒杀请求,最终只有 10 个订单会成功创建,也就是说有 990 的请求是无效的,这些无效的请求也会给数据库带来压力,因此可以在在请求落到数据库之前就将无效的请求过滤掉,将并发控制在一个可控的范围,这样落到数据库的压力就小很多 由于计数限流实现起来比较简单,因此采用计数限流,限流的实现可以直接使用 Guava 的 RateLimit 方法,但是由于后续需要将实例通过 Nginx 实现负载均衡,这里选用 Redis 实现分布式限流 在 RedisPool 中对 Jedis 线程池进行了简单的封装,封装了初始化和关闭方法,同时在 RedisPoolUtil 中对 Jedis 常用 API 进行简单封装,每个方法调用完毕则关闭 Jedis 连接。
  • SpringBoot使用@ComponentScan的Controller失效原因分析

    SpringBoot使用@ComponentScan的Controller失效原因分析 环境背景 在搭建整个架构过程中,启动类正常放在controller包外 启动类的注解如下: @SpringBootApplication @Slf4j @EnableTransactionManagement @EnableKafka @ComponentScan("com.seconds.dao") public class SecondsApplication { public static void main(String[] args) { SpringApplication.run(SecondsApplication.class, args); } } 造成项目启动后,controller包下的路径无法访问 @ComponentScan 默认扫描使用该注解的类所在的包,包括这个包下的类和子包, 所以如果没有配置basepackages,并且类都放在子包中,是可以正常访问的 * 如果配置了@ComponentScn中的basepackages,那么就要把所有需要扫描的包都配置. * 这种情况下,@ComponentScan是不会再去扫描当前类所在的包的. * 之前我之所以以为@ComponentScan对启动类之外的包无能为力, * 这里没有配置controller类的包,导致程序无法访问. * 这里必须配置扫描当前启动类的包,不然当前启动类对应的控制器将失效 修改成一下: @SpringBootApplication @Slf4j @EnableTransactionManagement @EnableKafka //@ComponentScan("com.seconds") @MapperScan(annotationClass = Repository.class, basePackages = "com.seconds.dao") public class SecondsApplication { public static void main(String[] args) { SpringApplication.run(SecondsApplication.class, args); } } //或者将当前的controller包也扫描到注解中 @SpringBootApplication @MapperScan(annotationClass = Repository.
  • Volatile的用途

    volatile的用途 1.线程可见性 package com.mashibing.testvolatile; public class T01_ThreadVisibility { private static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { new Thread(()-> { while (flag) { //do sth } System.out.println("end"); }, "server").start(); Thread.sleep(1000); flag = false; } } 2.防止指令重排序 问题:DCL单例需不需要加volatile? CPU的基础知识 缓存行对齐 缓存行64个字节是CPU同步的基本单位,缓存行隔离会比伪共享效率要高 Disruptor package com.mashibing.juc.c_028_FalseSharing; public class T02_CacheLinePadding { private static class Padding { public volatile long p1, p2, p3, p4, p5, p6, p7; // } private static class T extends Padding { public volatile long x = 0L; } public static T[] arr = new T[2]; static { arr[0] = new T(); arr[1] = new T(); } public static void main(String[] args) throws Exception { Thread t1 = new Thread(()->{ for (long i = 0; i < 1000_0000L; i++) { arr[0].