The Good Student！ - 中间件优化
type: channel
link: https://www.hxy.bj.cn/category/%E4%B8%AD%E9%97%B4%E4%BB%B6%E4%BC%98%E5%8C%96/
items: ELK 性能优化实践
items: ElasticSearch 性能调优
items: Nginx 性能调优

ELK 性能优化实践
type: item
date: 2025-07-27T22:46:06+08:00
description: 一、背景介绍近一年内对公司的 ELK 日志系统做过性能优化，也对 SkyWalking 使用的 ES 存储进行过性能优化，在此做一些总结。本篇主要是讲 ES 在 ELK 架构中作为日志存储时的性能优化方案。ELK 架构作为日志存储方案二、现状分析1. 版本及硬件配置JDK：JDK1.8\_171-b11 (64 位)ES集群：由3台16核32G的虚拟机部署 ES 集群，每个节点分配 20 G 堆内存ELK版本：6.3.0垃圾回收器：ES 默认指定的老年代（CMS）+ 新生代（ParNew）操作系统：CentOS Linux release 7.4.1708(Core)2. 性能问题随着接入 ELK 的应用越来越多，每日新增索引约 230 个，新增 document 约 3000 万到 5000 万。每日上午和下午是日志上传高峰期，在 Kibana 上查看日志，发现问题：(1) 日志会有 5-40 分钟的延迟(2) 有很多日志丢失，无法查到3. 问题分析3.1 日志延迟首先了解清楚：数据什么时候可以被查到？数据先是存放在 ES 的内存 buffer，然后执行 refresh 操作写入到操作系统的内存缓存 os cache，此后数据就可以被搜索到。所以，日志延迟可能是我们的数据积压在 buffer 中没有进入 os cache 。3.2 日志丢失查看日志发现很多 write 拒绝执行的情况write 线程池拒绝任务的日志.png从日志中可以看出 ES 的 write 线程池已经满负荷，执行任务的线程已经达到最大 16 个线程，而 200 容量的队列也已经放不下新的 task。查看线程池的情况也可以看出 write 线程池有很多写入的任务GET /_cat/thread_pool?v&h=host,name,type,size,active,largest,rejected,completed,queue,queue_sizewrite 线程池拒绝任务的情况.png所以我们需要优化 ES 的 write 的性能。4.解决思路4.1 分析场景ES 的优化分为很多方面，我们要根据使用场景考虑对 ES 的要求。根据个人实践经验，列举三种不同场景下的特点：SkyWalking：一般配套使用 ES 作为数据存储，存储链路追踪数据、指标数据等信息。ELK：一般用来存储系统日志，并进行分析，搜索，定位应用的问题。全文搜索的业务：业务中常用 ES 作为全文搜索引擎，例如在外卖应用中，ES 用来存储商家、美食的业务数据，用户在客户端可以根据关键字、地理位置等查询条件搜索商家、美食信息。这三类场景的特点如下： SkyWalkingELK全文搜索的业务并发写高并发写高并发写并发一般不高并发读并发低并发低并发高实时性要求5分钟以内30秒以内1分钟内数据完整性可容忍丢失少量数据可容忍丢失少量数据数据尽量100%不丢失关于实时性SkyWalking 在实际使用中，一般使用频率不太高，往往是发现应用的问题后，再去 SkyWalking 查历史链路追踪数据或指标数据，所以可以接受几分钟的延迟。ELK 不管是开发、测试等阶段，时常用来定位应用的问题，如果不能快速查询出数据，延迟太久，会耽误很多时间，大大降低工作效率；如果是查日志定位生产问题，那更是刻不容缓。全文搜索的业务中一般可以接受在1分钟内查看到最新数据，比如新商品上架一分钟后才看到，但尽量实时，在几秒内可以可看到。4.2 优化的方向可以从三方面进行优化：JVM 性能调优、ES 性能调优、控制数据来源三、ES性能优化可以从三方面进行优化：JVM 性能调优、ES 性能调优、控制数据来源1. JVM调优第一步是 JVM 调优。因为 ES 是依赖于 JVM 运行，没有合理的设置 JVM 参数，将浪费资源，甚至导致 ES 很容易 OOM 而崩溃。1.1 监控 JVM 运行情况（1）查看 GC 日志问题：Young GC 和 Full GC 都很频繁，特别是 Young GC 频率高，累积耗时非常多。(2) 使用 jstat 看下每秒的 GC 情况参数说明S0：幸存1区当前使用比例S1：幸存2区当前使用比例E：伊甸园区使用比例O：老年代使用比例M：元数据区使用比例CCS：压缩使用比例YGC：年轻代垃圾回收次数FGC：老年代垃圾回收次数FGCT：老年代垃圾回收消耗时间GCT：垃圾回收消耗总时间问题：从 jstat gc 中也可以看出，每秒的 eden 增长速度非常快，很快就满了。1.2 定位 Young GC 频繁的原因1.2.1 检查是否新生代的空间是否太小用下面几种方式都可查看新、老年代内存大小 (1) 使用 jstat -gc pid 查看 Eden 区、老年代空间大小 (2) 使用 jmap -heap pid 查…

ElasticSearch 性能调优
type: item
date: 2025-05-22T14:36:00+08:00
description: 来一个大的介绍：ElasticSearch的性能优化的几大方面本文借鉴尼恩博主，参考学习总的来说，ElasticSearch的性能优化，可以从以下方面的考虑：硬件层面的优化：机器分配，机器配置，机器内存，机器CPU，机器网络，机器磁盘性能系统层面的优化：文件句柄优化、swap关闭ElasticSearch集群层面的优化 重点合理分配节点，合理分配参加竞选Master的节点ElasticSearch 索引层面的优化 重点副本数量、索引数量、分片数量ElasticSearch查询层面的优化职责分离，全面监控1 硬件层面的优化1.1 为ES进行 硬件层面的 内存优化：Elasticsearch是一个内存密集型应用，合理分配内存对于Elasticsearch 提高性能至关重要:确保系统内存有足够的空间用于文件缓存，而不单单是JVM堆内存。建议将一半的内存分配给Elasticsearch的堆内存，另一半留给操作系统和其他进程。为了避免垃圾回收（GC）成为瓶颈，建议设置堆内存的最大值为30GB或更小。可以通过修改jvm.options文件来调整堆内存的大小。总之，ES是比较依赖内存的，并且对内存的消耗也很大，内存对ES的重要性甚至是高于CPU的，所以即使是数据量不大的业务，为了保证服务的稳定性，在满足业务需求的前提下，我们仍需考虑留有不少于20%的冗余性能。根据业务量不同，内存的需求也不同，一般生产建议总体 32内存，其中JVM 不要少于16G， 还有 16G给底层的Luence。为ES进行 系统层面的 磁盘优化对于ES来说，磁盘可能是最重要的了，因为数据都是存储在磁盘上的，当然这里说的磁盘指的是磁盘的性能。磁盘性能往往是硬件性能的瓶颈，木桶效应中的最短板。方式一：纵向扩展： 使用最高性能的 磁盘ES 磁盘优化的最为简单，最为粗暴的方式是 纵向扩展，就是使用最高性能的 磁盘，比如SSD 固态硬盘。ES应用可能要面临不间断的大量的数据读取和写入，数据规模非常庞大， 尼恩曾经架构过的一个30个节点ES集群，数据量非常庞大，达到1TB 。一般来说，速度最快的，也是最昂贵的。不可能都用SSD硬盘， 一般是 SSD和机械硬盘组合使用。所以，可以考虑把节点冷热分离：“热节点”使用SSD做存储，可以大幅提高系统性能；“冷数据“存储在机械硬盘中，降低成本。如果使用磁盘阵列，可以使用RAID 0。这里，尼恩给大家来点基础知识， 什么是RAID 0？RAID（Redundant Array of Independent Disks，独立磁盘冗余阵列）是一种将多个物理磁盘组合成一个逻辑单元的数据存储虚拟化技术，其目的是提高数据存储的性能、可靠性或两者兼顾。RAID 0 是RAID中一种配置方式，具体含义如下：RAID 0 定义：RAID 0 又称为条带化（Striping），它将数据分散存储在两个或多个硬盘上，每个硬盘只存储数据的一部分，从而提高数据的读写速度。工作原理：在RAID 0配置中，数据被分成多个块（称为“条带”），并按顺序存储在多个硬盘上。例如，如果有一个4KB的数据块，它会被分成4个1KB的块，分别存储在4个硬盘上。读取数据时，因为可以同时从多个硬盘读取，所以读取速度会加快。写入数据时也是同理，数据会被分成多个块并行写入多个硬盘。性能提升：RAID 0 的主要优势在于提高数据的读写速度。由于数据被分散在多个硬盘上，所以理论上，RAID 0 的读写速度可以达到单个硬盘速度的总和。没有冗余：RAID 0 的缺点是没有数据冗余。如果其中一个硬盘发生故障，整个阵列上的数据都会丢失，因为每个硬盘上只存储数据的一部分，没有副本。适用场景：RAID 0 适用于对性能要求高而对数据安全性要求不高的场景，如视频编辑、大型数据库的临时存储等。RAID 0 风险：由于没有数据冗余，RAID 0 的风险较高。一旦硬盘发生故障，整个RAID 0 阵列上的数据都会丢失，因此在使用RAID 0 时需要非常小心，并且定期备份数据。总结来说，RAID 0 是一种通过将数据分散存储在多个硬盘上来提高性能的配置方式，但它不提供任何数据冗余，因此使用时需要考虑到数据丢失的风险。这里，尼恩给大家再来点基础知识， 看看 RAID 0 和 RAID 1 的区别?RAID 0 和 RAID 1 是两种不同的RAID配置，RAID 0 和 RAID 1 在数据存储、性能和可靠性方面有显著的区别：RAID 0（条带化）： 多块磁盘并行读写数据存储：数据被分割成多个块（条带），然后分散存储在两个或多个硬盘上。这意味着每个硬盘上存储的是数据的不同部分，而不是数据的副本。性能：由于数据的读写操作可以并行进行，RAID 0 可以提供很高的数据传输速率，特别是在写入大量数据时。可靠性：RAID 0 没有数据…

Nginx 性能调优
type: item
date: 2025-05-16T11:00:00+08:00
description: 一、前言相信对于 Nginx 你一定并不陌生，它是一款轻量级的开源 Web 服务及代理程序，因其轻量化、支持高并发等特性，目前国内企业早已广泛的使用 Nginx。既然 Nginx 使用这么广泛，那么我们在性能测试工作中如何对其进行优化和配置便成了重中之重。二、配置优化2.1 并发处理架构优化2.1.1 工作进程配置现代 CPU 多核架构下，Nginx 的 worker 进程若在不同核心间频繁调度，会增加 CPU 上下文切换损耗。CPU 亲和性通过将 worker 进程固定到特定核心，避免跨核调度，提升缓存利用率。所以就需要配置 Nginx 的 CPU 亲和性来解决这个问题。那由于 Nginx CPU 亲和性配置本身有多套配置方案，这里推荐你直接将配置项设置成 auto（worker\_cpu\_affinity ），即采用了 Nginx 推荐的 CPU 绑核策略方式。另外的一个方式是手动绑定，将 worker 线程数量与 CPU 核心数一一绑定方式设置。我们设置成 auto Nginx 会自动识别并按照推荐策略来分配 worker 线程和 CPU。配置方案：自动绑定（推荐）：通过 worker_cpu_affinity auto 让 Nginx 自动识别 CPU 核心并按最优策略绑定。例如 8 核 CPU 会将 8 个 worker 进程一对一绑定到 CPU0\~CPU7，实现负载均衡。手动绑定：按核心数显式配置，如 worker_cpu_affinity 0001 0010 0100 1000（4 核场景）。配置示例如下：worker_cpu_affinity auto; # 自动将工作进程绑定到可用的 CPU 核心 worker_processes auto; # 基于CPU核心数动态分配工作进程，充分利用多核性能 worker_connections 1024; # 单进程最大并发连接数，支持高并发场景 worker_rlimit_nofile 65535; # 单进程文件描述符上限，突破系统资源限制 理论并发能力： 通过多进程模型实现水平扩展，总并发量为：worker\_processes × worker\_connections （例：4 核 CPU 配置下可达 4×1024=4096 并发连接）。需结合系统级限制（如 nofile）。若未调整 sysctl，实际并发可能受限于系统默认值（通常 1024）。# 系统级文件描述符限制 worker_rlimit_nofile 65535; # 需在系统中同步调整（/etc/security/limits.conf）2.1.2 事件驱动模型Linux 系统下一切皆文件，比如打开一个设备，它便会产生一个文件描述符。在产生一个进程时，这个进程便需要一个进程描述符，这个进程描述符也是一个文件。所以在 Nginx 处理请求的时候，每一个请求都会产生处理请求的描述符。其次，在 Nginx 处理大规模请求的时候，为了提高并发效率需要采用异步非阻塞模型，epoll 本身是以异步非阻塞模型来处理请求流中的事件流。这里还需要注意一点，并不是所有的 Linux 操作系统都可以使用 epoll，它是在 kernel 2.6 版本以后提出的，早期内核使用的 select\poll 模型，select 模型比 epoll 模型性能要低很多。模型对比：epoll（Kernel 2.6+）：异步非阻塞模型，基于事件驱动，通过 mmap 共享用户态与内核态空间，突破 select/poll 的 1024 文件描述符限制，支持百万级并发。select/poll：早期模型，需轮询扫描所有文件描述符，性能随并发量下降明显。配置示例如下：multi_accept on; # 一次性接受所有新连接 use epoll; # Linux高效IO多路复用，支持C10K级别并发 2.2 传输效率优化2.2.1 零拷贝技术Nginx 在处理文件时，会将文件传入操作系统内核态的 Buffer Cache，然后传递到操作系统上层的用户态，经用户态的 Buffer Cache 再传回内核态中，最后通过 Socket 将文件转发出去。通过 sendfile on 实现内核态直接传输，避免文件在用户态与内核态间的冗余拷贝。传统流程需 4 次拷贝（内核 Buffer→用户 Buffer→内核 Buffer→Socket），零拷贝仅需 2 次内核态数据搬运，尤其适合图片、视频等静态资源。配置示例如下：# I/O优化 - 减少带宽消耗和提高传输效率 sendfile on; # 开启零拷贝文件传输，减少CPU消耗和内核上下文切换 tcp_nopush on; # 优化数据包传输，减少网络报文数量，配合sendfile使用 tcp_no…