分布式-分布式高可用笔记

高可用的保障方式

双十一限制退款

  • 从业务角度考虑,由于活动期间流量巨大,订单产生数量过大,需要节省平台和商家的人力资源,节省库存盘点等工作;
  • 退款处理并不是核心流程,在双十一当天,商家也没有这么多的资源来处理退款请求,在服务治理中,这是典型的业务降级,保护系统,对非核心业务做降级处理。

电商大促的高可用保障

服务可用性是对服务等级协议 SLA 的描述。
假设一个核心链路依赖 10 个服务,这 10 个服务的可用性是 99.99%,那这个核心链路的可用性是 99.99% 的 10 次方,也就是 99.9%,可用性直接下降了一个等级,关联服务再多一些,可用性会更低。

在生产环境中,还要考虑服务发布、部署等导致的停机情况,可用性还会降低。

海量用户请求万倍日常流量,大促期间的流量是平时的千百倍甚至万倍,要做好容量规划,在平时的演练中需做好调度。目前大部分公司的部署都是应用 Docker 容器化编排,分布式需要快速扩展集群,而容器化编排操作简单,可以快速扩展实例。

流量突增,是典型的秒杀系统请求曲线,秒杀系统的流量是在瞬间达到一个峰值,流量曲线非常陡峭。为了吸引用户下单,电商大促一般都会安排若干场的秒杀抢购,为了应对这个特性,可以通过独立热点集群部署、消息队列削峰、相关活动商品预热缓存等方案来解决。

秒杀活动都会提前给用户预告商品,为了避免抢购时服务不可用,提前把相关商品数据都加载到缓存中,通过缓存来支撑海量请求。

高并发支撑海量用户请求,对于业务系统来说就是高并发,QPS 会是平时的几百倍甚至更高。如果在系统设计时没有考虑过高并发的情况,即使业务系统平时运行得好好的,如果并发量一旦增加,就会经常出现各种业务问题。比如,在电商业务中,可能会出现用户订单丢失、库存扣减异常、超卖等问题。

应对高并发,在前期系统设计时,考虑到并发系统容易出现的问题,比如在 Java 语言中,高并发时的 ThreadLocal 数据异常,数据库高并发的锁冲突、死锁等问题点,进行针对性的设计,避免出现业务异常。

电商大促面临的问题主要是支撑高并发和高可用,高可用常见的手段有缓存、消息队列。

避免服务雪崩问题、链路问题、故障传导。

由于微服务调用通常是通过一个链路的形式进行,各个服务之间是一个调用链,牵一发而动全身,某个服务提供者宕机,可能导致整个链路上的连续失败,出现整体超时,最后可能导致业务系统停止服务。

避免服务雪崩问题,可以限流、降级、熔断、隔离。

系统限流

常见限流算法

限流是服务降级的一种手段,顾名思义,通过限制系统的流量,从而实现保护系统的目的。

合理的限流配置,需要了解系统的吞吐量,所以,限流一般需要结合容量规划和压测来进行。当外部请求接近或者达到系统的最大阈值时,触发限流,采取其他的手段进行降级,保护系统不被压垮。常见的降级策略包括延迟处理、拒绝服务、随机拒绝等。

限流后的策略,其实和 Java 并发编程中的线程池非常类似,线程池在任务满的情况下,可以配置不同的拒绝策略,比如:

  • AbortPolicy,会丢弃任务并抛出异常;
  • DiscardPolicy,丢弃任务,不抛出异常;
  • DiscardOldestPolicy 等,当然也可以自己实现拒绝策略。

判断当前的流量已经达到设置的最大值。

计数器法

限流时使用的是单位时间内的请求数 QPS,统计 QPS 最直接的想法就是实现一个计数器。

假设一个接口限制 100 秒内的访问次数不能超过 10000 次,维护一个计数器,每次有新的请求过来,计数器加 1。这时候判断,如果计数器的值小于限流值,并且与上一次请求的时间间隔还在 100 秒内,允许请求通过,否则拒绝请求;如果超出了时间间隔,要将计数器清零。

下面的代码里使用 AtomicInteger 作为计数器,可以作为参考:

public class CounterLimiter { 
    //初始时间 
    private static long startTime = System.currentTimeMillis(); 
    
    //初始计数值 
    private static final AtomicInteger ZERO = new AtomicInteger(0); 

    //时间窗口限制 
    private static final int interval = 10000; 

    //限制通过请求 
    private static int limit = 100; 

    //请求计数 
    private AtomicInteger requestCount = ZERO; 

    //获取限流 
    public boolean tryAcquire() { 

        long now = System.currentTimeMillis(); 
        //在时间窗口内 
        if (now < startTime + interval) { 
            //判断是否超过最大请求 
            if (requestCount.get() < limit) { 

 requestCount.incrementAndGet(); 
                return true; 
            } 
            return false; 
        } else { 

            //超时重置 
            requestCount = ZERO; 
            startTime = now; 
            return true; 
        }
    } 
} 

计数器策略进行限流,可以从单点扩展到集群,适合应用在分布式环境中。单点限流使用内存即可,如果扩展到集群限流,可以用一个单独的存储节点,比如 Redis 或者 Memcached 进行存储,在固定的时间间隔内设置过期时间,就可以统计集群流量,进行整体限流。

缺点是对临界流量不友好,限流不够平滑。
假设限制用户一分钟下单不超过 10 万次,现在在两个时间窗口的交汇点,前后一秒钟内,分别发送 10 万次请求。也就是说,窗口切换的这两秒钟内,系统接收了 20 万下单请求,这个峰值可能会超过系统阈值,影响服务稳定性。

漏桶和令牌桶算法

漏桶算法可以用漏桶来对比,假设现在有一个固定容量的桶,底部钻一个小孔可以漏水,通过控制漏水的速度,来控制请求的处理,实现限流功能。

漏桶算法的拒绝策略很简单,如果外部请求超出当前阈值,则会在水桶里积蓄,一直到溢出,系统并不关心溢出的流量。漏桶算法是从出口处限制请求速率,并不存在上面计数器法的临界问题,请求曲线始终是平滑的。

漏桶算法的一个核心问题是,对请求的过滤太精准了,限制每秒下单 10 万次,那 10 万零 1 次请求呢?是不是必须拒绝掉呢?

大部分业务场景下这个答案是否定的,虽然限流了,但还是希望系统允许一定的突发流量,这时候就需要令牌桶算法。

在令牌桶算法中,假设有一个大小恒定的桶,这个桶的容量和设定的阈值有关,桶里放着很多令牌,通过一个固定的速率,往里边放入令牌,如果桶满了,就把令牌丢掉,最后桶中可以保存的最大令牌数永远不会超过桶的大小。

当有请求进入时,就尝试从桶里取走一个令牌,如果桶里是空的,那么这个请求就会被拒绝。

Google 的在Guava 中,就有限流策略的工具类 RateLimiter,RateLimiter 基于令牌桶算法实现流量限制,使用非常方便。

RateLimiter 会按照一定的频率往桶里扔令牌,线程拿到令牌才能执行,RateLimter 的 API 可以直接应用,主要方法是 acquire 和 tryAcquire,acquire 会阻塞,tryAcquire 方法则是非阻塞的。下面是一个简单的示例:

public class LimiterTest { 

    public static void main(String[] args) throws InterruptedException { 

        //允许10个,permitsPerSecond 

        RateLimiter limiter = RateLimiter.create(100); 

        for(int i=1;i<200;i++){ 

            if (limiter.tryAcquire(1)){ 

                System.out.println("第"+i+"次请求成功"); 

            }else{ 

                System.out.println("第"+i+"次请求拒绝"); 

            } 

        } 

    } 

} 
 

不同限流算法的比较

计数器算法实现比较简单,特别适合集群情况下使用,但是要考虑临界情况,可以应用滑动窗口策略进行优化,当然也是要看具体的限流场景。

漏桶算法和令牌桶算法,漏桶算法提供了比较严格的限流,令牌桶算法在限流之外,允许一定程度的突发流量。在实际开发中,我们并不需要这么精准地对流量进行控制,所以令牌桶算法的应用更多一些。

如果我们设置的流量峰值是 permitsPerSecond=N,也就是每秒钟的请求量,计数器算法会出现 2N 的流量,漏桶算法会始终限制N的流量,而令牌桶算法允许大于 N,但不会达到 2N 这么高的峰值

降级和熔断

高可用之降级

在大促场景下,请求量剧增,系统资源是有限的,服务器资源是企业的固定成本,这个成本不可能无限扩张,所以说,降级是解决系统资源不足和海量业务请求之间的矛盾

降级的具体实现手段是,在暴增的流量请求下,对一些非核心流程业务、非关键业务,进行有策略的放弃,以此来释放系统资源,保证核心业务的正常运行。

例如:电商大促时限制退款,但平时并不会限制,所以服务降级不是一个常态策略,而是应对非正常情况下的应急策略。服务降级的结果,通常是对一些业务请求,返回一个统一的结果,你可以理解为是一种 FailOver 快速失败的策略。

举个例子,我们都有在 12306 网站购票的经历,在早期春运抢票时,会有大量的购票者进入请求,如果火车票服务不能支撑,一般都会返回一个空的信息,这其实是一种限流后的策略,从一个广义的角度去理解,限流也是一种服务降级手段,是针对部分请求的降级。

降级针对的目标,一般是业务闭环中的一些次要功能,比如大促时的评论、退款功能,从一致性的角度,因为强一致性的保证需要很多系统资源,降级可能会降低某些业务场景的一致性。

注意:首先需要注意梳理核心流程,知道哪些业务是可以被牺牲的,比如双十一大家都忙着抢购,这时候一些订单评论之类的边缘功能,就很少有人去使用。另外,要明确开启时间,在系统水位到达一定程度时开启。

高可用之熔断

在很多证券市场上,在大盘发生非常大幅度的波动时,为了保护投资者的利益,维护正常的市场秩序,会采取自动停盘机制,也就是常说的股市熔断

在高可用设计中,也有熔断的技术手段,熔断模式保护的是业务系统不被外部大流量或者下游系统的异常而拖垮。

通过添加合理的熔断策略,可以防止系统不断地去请求可能超时和失败的下游业务,跳过下游服务的异常场景,防止被拖垮,也就是防止出现服务雪崩的情况。

熔断策略其实是一种熔断器模式,一个设计完善的熔断策略,可以在下游服务异常时关闭调用,在下游服务恢复正常时,逐渐恢复流量。

例子:假设你开发了一个电商的订单服务,你的服务要依赖下游很多其他模块的服务,比如评论服务。现在有一个订单查询的场景,QPS 非常高,但是恰好评论服务因为某些原因部分机器宕机,出现大量调用失败的情况。如果没有熔断机制,订单系统可能会在失败后多次重试,最终导致大量请求阻塞,产生级联的失败,并且影响订单系统的上游服务,出现类似服务雪崩的问题,导致整个系统的响应变慢,可用性降低。

如果开启了熔断,订单服务可以在下游调用出现部分异常时,调节流量请求,比如在出现 10% 的失败后,减少 50% 的流量请求,如果继续出现 50% 的异常,则减少 80% 的流量请求;相应的,在检测的下游服务正常后,首先恢复 30% 的流量,然后是 50% 的流量,接下来是全部流量。

对于熔断策略的具体实现,查看 Alibaba Sentinel 或者 Netflix Hystrix 的设计,熔断器的实现其实是数据结构中有限状态机(Finite-state Machines,FSM)的一种应用,因为 FSM 不光在算法领域有应用,在复杂系统设计时,为了更好的标识状态流转,用有限状态机来描述会特别清晰。

熔断器的恢复时间,也就是平均故障恢复时间,称为 MTTR,在稳定性设计中是一个常见的指标,在 Hystrix 的断路器设计中,有以下几个状态。

  • Closed:熔断器关闭状态,比如系统检测到下游失败到了 50% 的阈值,会开启熔断。
  • Open:熔断器打开状态,此时对下游的调用在内部直接返回错误,不发出请求,但是在一定的时间周期以后,会进入下一个半熔断状态。
  • Half-Open:半熔断状态,允许少量的服务请求,如果调用都成功(或一定比例)则认为恢复了,关闭熔断器,否则认为还没好,又回到熔断器打开状态。

在系统具体实现中,降级和熔断推荐使用成熟的中间件,包括 Sentinel 和 Hystrix,以及 resilience4je

Sentinel 官网

几种组件的对比,来自阿里巴巴 Sentinel 开发团队的分享,作为补充资料:

Sentinel Hystrix resilience4j
隔离策略 信号量隔离(并发线程数限流) 线程池隔离/信号量隔离 信号量隔离
熔断降级策略 基于响应时间、异常比率、异常数 基于异常比率 基于异常比率、响应时间
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于 RxJava) Ring Bit Buffer
动态规则配置 支持多种数据源 支持多种数据源 有限支持
扩展性 多个扩展点 插件的形式 接口的形式
基于注解的支持 支持 支持 支持
限流 基于 QPS,支持基于调用关系的限流 有限的支持 Rate Limiter
流量整形 支持预热模式、匀速器模式、预热排队模式 不支持 简单的 Rate Limiter 模式
系统自适应保护 支持 不支持 不支持
控制台 提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等 简单的监控查看 不提供控制台,可对接其他监控系统

负载均衡策略选择

负载均衡的应用

负载均衡是指如何将网络请求派发到集群中的一个或多个节点上处理,传统的负载均衡可以分为硬件负载均衡和软件负载均衡。

  • 硬件负载均衡,就是通过专门的硬件来实现负载均衡,比如常见的 F5 设备。
  • 软件负载均衡则是通过负载均衡软件实现,常见的就是 Nginx。

无论是硬件负载均衡还是软件负载均衡,实现原理都是一样的,在负载均衡中会记录一个可用的服务列表,负载均衡服务器会通过心跳机制来确认服务可用性,在网络请求到达后,F5 或者 Nginx 等负载均衡设备,会按照不同的策略,进行服务器的路由,这就是负载均衡的流程。

负载均衡的应用非常广,这一课时我们主要关注在分布式系统的请求调用,服务分发中的负载均衡。

常见的复杂均衡策略

轮询策略

轮询策略会顺序地从服务器列表中选择一个节点,请求会均匀地落在各个服务器上。轮询适合各个节点性能接近,并且没有状态的情况,但是在实际开发中,不同节点之间性能往往很难相同,可以应用加权轮询策略

加权轮询

加权轮询是对轮询策略的优化,给每个节点添加不同的权重。
例:在实际开发中通常使用数组的数据结构来实现轮询,比如现在有 A、B、C 三个节点,可以在数组中添加 1、2、3 的数据,分别对应三个节点。现在进行加权调整,让 1、2、3 对应 A,4、5 对应 B、C,这时候继续进行轮询,不同节点的权重就有变化了。

随机策略

随机策略和轮询相似,从列表中随机的取一个。如果访问量不是很大,最好不要应用随机策略,可能会导致请求不均匀。

最小响应时间

主要在一些对请求延时敏感的场景中,路由时,会优先发送给响应时间最小的节点。

最小并发数策略

对比最小响应时间,最小并发策略会记录当前时刻每个节点正在处理的事务数,在路由时选择并发最小的节点。最小并发策略可以比较好地反应服务器运行情况,适用于对系统负载较为敏感的场景。

除了这些,还有哈希策略等

负载均衡如何实现

在分布式服务调用中,根据负载均衡实现的位置不同,可以分为服务端负载均衡和客户端负载均衡。

  • 在服务器端负载均衡中,请求先发送到负载均衡服务器,然后通过负载均衡算法,在众多可用的服务器之中选择一个来处理请求。
  • 在客户端负载均衡中,不需要额外的负载均衡软件,客户端自己维护服务器地址列表,自己选择请求的地址,通过负载均衡算法将请求发送至该服务器。

区别:服务器列表维护的位置。

在分布式服务调用中,服务端负载均衡常用的组件是 Spring Cloud Eureka,如果你选择了 Dubbo 作为中间件,那么可以应用 Dubbo 内置的路由策略。

在 Spring Cloud 中开启负载均衡的方法很简单,有一个专门的注解 @LoadBalanced 注解,配置这个注解之后,客户端在发起请求的时候会选择一个服务端,向该服务端发起请求,实现负载均衡。另外一种客户端负载均衡,也有对应的实现,典型的是 Spring Cloud Ribbon。

Ribbon 实际上是一个实现了 HTTP 的网络客户端,内置负载均衡工具、支持多种容错等。

稳定性指标

系统监控的重要性

系统监控可以分为三个方面,分别是监控组件、监控指标、监控处理

稳定性指标有哪些

稳定性指标,分为服务器指标、系统运行指标、基础组件指标和业务运行时指标。

Open-Falcon 的监控采集,地址为 Linux 运维基础采集项。

服务器监控指标

服务器指标主要关注的是虚拟机或者 Docker 环境的运行时状态,包括 CPU 繁忙程度、磁盘挂载、内存利用率等指标。

服务器是服务运行的宿主环境,如果宿主环境出问题,服务很难保持稳定性,所以服务器监控是非常重要的。常见的服务器报警包括 CPU 利用率飙升、磁盘空间容量不足、内存打满等。

监控项 指标描述
CPU 空闲时间 除硬盘 IO 等待时间以外其他等待时间,这个值越大,表示 CPU 越空闲
CPU 繁忙程度 和 CPU 空闲时间相反
CPU 负载 CPU 负载(如果是 Docker,此指标收集物理机的 load)和 CPU 利用率监控
CPU 的 iowait 在一个采样周期内有百分之几的时间属于以下情况:CPU 空闲且有仍未完成的 I/O 请求
CPU 的 system CPU 用于运行内核态进程的时间比例
CPU 的 user CPU 用于运行用户态进程的时间比例
load1 表示最近 1 分钟内运行队列中的平均进程数量
load3 表示最近 5 分钟内运行队列中的平均进程数量
load15 表示最近 15 分钟内运行队列中的平均进程数量(在 falcon 系统里)
磁盘使用情况 磁盘使用情况,磁盘已用,未使用容量

服务器的指标,在实际配置中,需要根据服务器核心数不同,以及不同的业务特点配置不同的指标策略。比如,如果是一个日志型应用,需要大量的磁盘资源,就要把磁盘报警的阈值调低。

系统运行指标

系统指标主要监控服务运行时状态、JVM 指标等,这些监控项都可以在 Open-Falcon 等组件中找到,比如 JVM 的 block 线程数,具体在 Falcon 中指标是 jvm.thread.blocked.count。

监控项 指标描述 说明
JVM 线程数 线程总数量 关注整体线程运行情况
JVM 阶段线程增长 累计启动线程数量 线程应该尽量复用,因此不宜持续创建新线程
JVM 死锁 死锁个数 线程死锁,一般都不能忍受
JVM 的 block 线程数 blocked 状态的线程数 blocked 状态的线程过多,说明程序遭遇剧烈的锁竞争
GC 的次数 GC 的次数 垃圾回收的这几个指标,通常会综合来看,在进行调优时非常重要
GC 时间 GC 的时间
年轻代 GC 年轻代 GC 的次数
老年代 GC 次数 年老代 GC 的次数
老年代 GC 时间 年老代 GC 的时间

基础组件指标

在基础组件这里,主要包括对数据库、缓存、消息队列的监控,下面我以数据库为例进行描述,虽然各个中间件对数据库监控的侧重点不同,但是基本都会包括以下的监控项。

监控项 指标描述
写入 QPS 数据库写入 QPS
数据库查询 QPS 查询 QPS
数据库的死锁 死锁处理不及时可能导致业务大量超时
数据库慢查询 QPS 慢查询 QPS
数据库的活跃连接数 数据库的活跃连接数
数据库的总连接数 数据库的总连接数
数据库 Buffer Pool 命中率 可能引起数据库服务抖动,业务系统不稳定

在进行数据库优化时要综合这部分指标,根据具体业务进行配置。

业务运行时指标

业务运行时指标需要根据不同的业务场景来配置。

举个例子,你现在开发的是一个用户评论系统,那么就需要关注每天用户评论的请求数量、成功率、评论耗时等。业务指标的配置,需要结合各类监控组件,在指标的选择上,通常需要结合上下游各个链路,明确哪些是核心链路,并且进行指标的分级。

监控组件

常用监控组件

目前分布式系统常用的监控组件主要有 OpenFalcon、Nagios、Zabbix、CAT 等

OpenFalcon

Open-Falcon 是小米开源的一款企业级应用监控组件,在很多一线互联网公司都有应用,已经成为国内最流行的监控系统之一。

Open-Falcon 是监控指标最完善的监控组件之一。Falcon有一个特点,它是第一个国内开发的大型开源监控系统,所以更适合国内互联网公司的应用场景,在使用上,Open-Falcon 也要比其他的监控组件更加灵活,关于Open-Falcon 的监控指标,你可以在官网上了解更多的信息:Open-Falcon 官网。

Zabbix

Zabbix 基于 Server-Client 架构,和 Nagios 一样,可以实现各种网络设备、服务器等状态的监控。Zabbix 的应用比较灵活,数据存储可以根据业务情况,使用不同的实现,比如 MySQL、Oracle 或 SQLite 等,Zabbix 的 Server 使用 C 语言实现,可视化界面基于 PHP 实现。

Zabbix 整体可以分为 Zabbix Server 和 Zabbix Client,即 Zabbix Agent,Zabbix对分布式支持友好,可以对各类监控指标进行集中展示和管理,并且有很好的扩展性,采用了微内核结构,可以根据需要,自己开发完善各类监控。

如果希望了解更多具体的应用,还可以去 Zabbix 官网了解相关的内容:ZABBIX 产品手册。

Nagios

Nagios(Nagios Ain’t Goona Insist on Saintood)是一款开源监控组件,和 Zabbix 等相比,Nagios 支持更丰富的监控设备,包括各类网络设备和服务器,并且对不同的操作系统都可以进行良好的兼容,支持 Windows 、Linux、VMware 和 Unix 的主机,另外对各类交换机、路由器等都有很好的支持。
Nagios 对各类网络协议下的监控支持非常好。

Nagios 虽然监控报警能力强大,但是配置比较复杂,各种功能都要依靠插件来实现,图形展示效果很差。从这个角度来看,Nagios 的应用更加偏向运维。

Nagios 还可以监控网络服务,包括 SMTP、POP3、HTTP、NNTP、PING 等,支持主机运行状态、自定义服务检查,可以进行系统状态和故障历史的查看,另外,使用 Nagios 可以自定义各种插件实现定制化的功能点击这里查看官网了解一下。

CAT

CAT(Central Application Tracking)早期是大众点评内部的监控组件,2014 年开源,并且在携程、陆金所、猎聘网等大型互联网公司内部广泛应用。

CAT 基于 Java 开发,特别适合 Java 技术栈的公司,对分布式系统支持非常好。在社区开源以后,CAT 又加入了很多特性功能,已经成为一个大而全的应用层统一监控组件,对各类分布式服务中间件、数据库代理层、缓存和消息队列都有很好的支持,可以为业务开发提供各个系统的性能指标、健康状况,并且还可以进行实时告警。

相比其他偏向运维的监控组件,比如 Nagios、Cat 更加关注应用层面的监控指标,支持性能埋点和优化,对开发工程师更加友好。我在工作中和 CAT 打交道比较多,比较推荐这款监控组件,大家有机会可以在自己的公司里推广使用。

点击这里查看 CAT 项目的开源地址,另外附上点评技术团队发表的技术文章:

  • CAT 3.0 开源发布,支持多语言客户端及多项性能提升
  • 深度剖析开源分布式监控 CAT

监控处理制度

大型互联网公司都非常重视服务稳定性工作,因为服务稳定性直接影响用户体验,影响公司产品在用户心中的口碑,线上服务稳定性是开发者需要重点关注的

原则:

  • 发现故障,第一时间同步到相关业务负责人,上下游链路;
  • 第一时间快速恢复业务,快速进行故障止血;
  • 及时协调资源,避免故障升级;
  • 事后进行故障复盘和总结,避免再次出现类似问题。

线上告警和故障吸取到很多教训,提升服务的稳定性,更好的支持业务

统一日志系统

传统的日志查看

Linux 查看日志的命令有多种:tail、cat、head、more 等

  • tail 和 head 命令

tail 是我最常用的一种查看方式,典型的应用是查看日志尾部最后几行的日志,一般会结合 grep 进行搜索应用:

tail -n 10 test.log tail -fn 1000 test.log | grep ‘test’

head 和 tail 相反,是查看日志文件的前几行日志,其他应用和 tail 类似:

head -n 10 test.log

  • more 和 less

more 命令可以按照分页的方式现实日志内容,并且可以进行快速地翻页操作,除了 more 命令以外,常用的还有 less 命令,和 more 的应用类似。

  • cat

cat 命令用于查看全部文件,是由第一行到最后一行连续显示在屏幕上,一次显示整个文件,一般也会结合 grep 等管道进行搜索。

除了基本的指令以外,还有 AWK 和 SED 命令,用于比较复杂的日志分析,例如,sed 命令可以指定对日志文件的一部分进行查找,根据时间范围,或者根据行号等搜索。关于 AWK 和 SED 详细的应用说明,你可以结合 help 指令查看命令示例。不过呢,我的建议是只要了解基本操作就可以,一些比较复杂的语法可以通过查看手册或者搜索类似的命令行应用来实现:

  • The GNU Awk User’s Guide
  • sed, a stream editor

统一日志系统

在分布式场景下,除了不方便查看集群日志以外,传统日志收集都存在哪些问题?

  • 无法实现日志的快速搜索

传统的查找是基于文件的,搜索效率比较低,并且很难对日志文件之间的关系进行聚合,无法从全局上梳理日志,也很难进行调用链路的分析。

  • 日志的集中收集和存储困难

当有上千个节点的时候,日志是分布在许多机器上的,如果要获取这些日志的文件,不可能一台一台地去查看,所以这就是很明显的一个问题。

  • 日志分析聚合及可视化

由于日志文件分布在不同的服务器上,因此进行相关的分析和聚合非常困难,也不利于展开整体的数据分析工作。

除了这些,还有日志安全问题,以电商场景为例,很多业务日志都是敏感数据,比如用户下单数据、账户信息等,如何管理这些数据的安全性,也是一个很关键的问题。

ELK 统一日志系统

ElasticSearch 内核使用 Lucene 实现,实现了一套用于搜索的 API,可以实现各种定制化的检索功能,和大多数搜索系统一样,ElasticSearch 使用了倒排索引实现

Logstash 同样是 ElasticSearch 公司的产品,用来做数据源的收集,是 ELK 中日志收集的组件。
分布式-分布式高可用笔记_第1张图片
Logstash 的数据流图如上图所示,可以把 Logstash 想象成一个通用的输入和输出接口,定义了多种输入和输出源,可以把日志收集到多种文件存储中,输出源除了 ElasticSearch,还可以是 MySQL、Redis、Kakfa、HDFS、Lucene 等。

Kibana 其实就是一个在 ElasticSearch 之上封装了一个可视化的界面,但是 Kibana 实现的不只是可视化的查询,还针对实际业务场景,提供了多种数据分析功能,支持各种日志数据聚合的操作。

ELK 系统进行日志收集的过程可以分为三个环节,如下图所示
分布式-分布式高可用笔记_第2张图片

  • 使用 Logstash 日志收集,导入 ElasticSearch

Logstash 的应用非常简单,核心配置就是一个包含 input{}、filter{}、output{} 的文件,分别用来配置输入源、过滤规则和配置输出。下面的配置是一个典型的实例:

input {

file {

path => "/Users/test/log"

start_position => beginning

}

}

filter {

grok {

match => { "message" => "%{COMBINE}"}

}

}

output {

ElasticSearch {}

stdout {}

}
  • 在 ElasticSearch 中实现索引处理

日志数据导入到 ElasticSearch 中以后,实现索引,在这一步中,可以针对不同日志的索引字段进行定制。

  • 通过 Kibana 进行可视化操作、查询等

作为一个商业化产品,Kibana 已经支持了非常丰富的日志分析功能,并且可以选择应用一些机器学习的插件,可以在 Kibana 的官方文档中了解更多。

使用 Flume 进行容器内的日志收集,并且将日志消息通过 Kakfa 传送给 Logstash,最后在 Kibana 中展示。
补充阅读:ELK 统一日志系统的应用。

你可能感兴趣的:(分布式,分布式)