Go 怎么做性能优化芝麻开门篇

news/2024/12/16 19:44:09/

一、性能优化的流程

我们在对某个功能(或单个接口)做性能优化的时候。一般是该功能(或接口)性能无法满足我们的业务要求,所以被迫优化。在开始优化之前,我们需要明白一些理论知识。

1、常见的性能优化指标
1.1 响应时间
  • 定义:接口从接收到请求到返回响应所需的时间。
  • 常见优化方法:
    • 缓存:减少对数据库或后端系统的频繁访问。
    • 异步处理:将耗时操作放到后台,避免阻塞主线程。
    • 数据压缩:减小返回的数据量,减少传输时间。
    • 优化算法:使用高效的算法和数据结构
1.2 并发数
  • 定义:接口能够同时处理的并发请求数量。
  • 常见优化方法:
    • 增加并发连接池:避免线程或数据库连接的瓶颈。
    • 限流(Rate Limiting):通过限制并发请求数,保证系统稳定性。
    • 适当配置线程池、数据库连接池等资源。
1.3 吞吐量
  • 定义:单位时间内,接口可以处理的请求数量。通常以每秒请求数(RPS)来表示。
  • 常见优化方法:
    • 使用负载均衡:通过多个服务器分担请求压力。
    • 数据库优化:通过分库分表、索引等方法提高数据库查询性能。
    • 使用高效的缓存策略,减少对后端的访问。
    • 异步化操作,提升并发处理能力。
1.4 资源消耗
  • 定义:接口处理请求时消耗的系统资源(如 CPU、内存、I/O)。
  • 常见优化方法:
    • 优化数据处理流程,减少不必要的计算。
    • 使用合适的缓存机制,避免重复计算。
    • 监控和优化内存使用,防止内存泄漏。
    • 使用合适的压缩算法,减少 I/O 操作。

这里有人可能会对RPS有点不大熟悉,那么它和QPS的区别是什么呢?

2.QPS和RPS的区别
2.1 QPS(Queries Per Second)
  • 定义:QPS 表示系统每秒钟处理的查询次数,通常用于描述 数据库查询 或 搜索引擎 的查询频率。

  • 使用场景:QPS 多用于衡量查询系统(如数据库、缓存系统、搜索引擎等)的处理能力,反映的是系统能够处理的查询请求的数量。

    例如:对于一个数据库,QPS 可能表示每秒从数据库中查询的记录数。如果某个搜索引擎的 QPS 为 1000,意味着每秒钟有 1000 个查询请求提交到搜索引擎,它需要处理并返回相应的搜索结果。

2.2 RPS(Requests Per Second)
  • 定义:RPS 表示系统每秒钟能够处理的请求次数。RPS 一般用于描述 Web 服务器 或 API 接口 的吞吐量,反映的是系统接受并处理请求的能力。
  • 使用场景:RPS 多用于 Web 应用、API 服务、负载均衡器等,描述这些系统在处理 HTTP 请求时的能力。
    例如:对于一个 Web 服务器,RPS 可能表示每秒处理的 HTTP 请求数量。如果某个 Web 服务器的 RPS 为 5000,意味着每秒钟该服务器可以处理 5000 个 HTTP 请求。
指标区别常用场景
QPS每秒查询次数,常用于数据库或查询引擎数据库、缓存、搜索引擎
RPS每秒请求次数,常用于衡量 Web 服务器或 API 的吞吐量Web 服务器、API 接口

实际上,QPS 是针对查询类操作的吞吐量度量,RPS 是针对网络请求的吞吐量度量。

3、性能优化怎么做
3.1 确定性能优化目标

在开始做性能优化之前,首先你要明确你的优化目标是什么,不同的优化目标对应着不同的优化策略,确定好性能优化目标,一方面可以避免过度优化,另一方面,是避免优化不足导致我们的系统无法继续支持后续发展。比如说,接口的QPS要达成多少,接口延迟需要达到多少,通过这些目标,才能明确我们的优化是否达标。

怎么算过度优化呢,比如说,一个内部系统页面查询太慢了,现在需要2s,然后你大费周章把它优化到了10ms , 花费了大量的时间和人力调整服务架构,搞分布式,提高了系统的复杂性,增大了系统维护成本,就没太大必要,因为它只是一个内部系统,我们在做任何决策的时候,都需要权衡我们的付出和收获,即ROI思想,把核心的资源用在核心的部分上

我们可以根据实际业务情况,来设定目标,例如搞活动的时候,我们要大概预估会有多少的活动用户,来确定某个查询接口的QPS,在评估上要有一定的系统冗余,即在保守估计上✖️个1.2~1.5倍,这样即使估摸不准确,或者突然有更多的参与用户,我们的系统也可以保证尽量不出问题。

确定性能目标,需要基于你手中拥有的资源和实际业务,做决策和权衡,比如说在保证接口时延不变的情况下,提高单机的QPS

说实话,决策和权衡能力很依赖一个人的经验,当然如果我们自己没有太多经验,那么我们可以去借鉴别人的经验。多实践多思考,必有收获。

3.2 找到瓶颈

为了更好的找到某个功能的瓶颈,我们可以对这个功能进行性能测试,单个请求测试和集群整体压测(全链路压测)。

单个请求测试的目的是确定我们自己的服务是否存在可优化点,比如接口延时是否符合预期,服务资源的使用是否合理,有没有异常报错

全链路压测的目的则是针对某个具体的功能进行上下游压测,方便我们找到整个链路中其他服务的卡点,来确定瓶颈是在本服务还是其他服务。

经常做活动服务的朋友应该对这方面比较有认知,活动对接口时延,QPS等要求都特别高,因此每次活动前都要模拟压测,确保活动当天不会出问题,一般都是进行全链路压测,通过链路追踪工具可以方便的看出具体是在哪个节点比较慢(本质上就是打日志分析),如果是本服务的瓶颈,我们可以针对性对具体的接口进行优化,如果是其他下游服务的瓶颈,则需要让其他团队帮忙优化。

当瓶颈点有多个时,我们可以找到最大的影响瓶颈,一步步做优化,为了控制好改造的成本,先解决一个相对好解决或者说是改造价值比较大的瓶颈,后续性能目标达不到再继续优化其他的点。

3.2 怎么对瓶颈进行优化

找到了瓶颈之后,我们就要分析瓶颈的原因是什么,不同的瓶颈分析的思路也是不同的。

如果是本服务的接口:在压测过程中,我们可以观察服务的资源消耗情况(内存、CPU、协程数),通过资源的使用情况来判断接口存在的问题。如果发现是内存的消耗过高导致单机吞吐量低,可以通过 pprof 抓取内存的火焰图,看具体是哪段代码在频繁的分配内存

而对于下游组件的瓶颈,例如说mysql。有一些常见的分析思路:

1、是否是服务调用 MySQL 的 IO 时间过长,这种情况可以看下是不是返回的数据量过大。
2、查看我们的 MySQL 请求是否存在慢查询,判断 SQL、索引使用合不合理。
3、如果排除了上述两个因素,需要分析下是否是因为我们的表太大、从库不够,还是说 MySQL 本身支持不了这么高的吞吐和这么严的延时要求

本质上观察几个点。

  • 服务和mysql的连接是否正常(连接池、网络等)
  • mysql 的响应是否正常(慢查询、查询量等)

针对Go来说。一个接口的瓶颈常见的问题有如下几点。

  • 网络吞吐量
  • Go服务资源限制
  • 代码逻辑
  • 下游组件的瓶颈

用人话说,首先可以先看看是不是代码问题,代码是不是有存在循环的数据库查询,可以改成批量查询来优化,同步操作能不能改成异步处理,内存使用是否合理,有没有内存泄漏,有没有协程泄漏,能不能加缓存层,网络调用是否有复用连接。

网络本身是否有问题,带宽,网络延迟。

服务的资源(内存、CPU、硬盘)够不够用

下游服务是不是高性能的组件。使用方式是否正确。

3.3 验证目标达成

为了验证性能目标是否达成,我们可以对调优过的应用进行性能测试,与优化前的各项指标进行对比,观测其是否符合预期。

如果瓶颈点没有消除或者性能指标不符合预期,则需要重复找瓶颈点、瓶颈分析、性能调优和验证目标是否达成的步骤,直到达成性能目标

在这里插入图片描述

二、性能优化的工具(篇幅太长没必要,第二篇再写)

pprof 工具
benchmark 功能
trace 工具

http://www.ppmy.cn/news/1555664.html

相关文章

【Java学习笔记】Map 接口实现类-HashMap

一、HashMap 小结 二、HashMap 底层机制及源码剖析 package com.hspedu.map_; import java.util.HashMap; /** * author 韩顺平 * version 1.0 */ SuppressWarnings({"all"}) public class HashMapSource1 { public static void main(String[] args) { HashMap map …

SpringBoot:快速构建微服务应用

一、SpringBoot简介 什么是SpringBoot 是由Pivotal团队提供的快速开发框架。它基于Spring框架,可以用于快速构建微服务应用程序。SpringBoot提供了一种快速、便捷的方式来启动和配置一个基于Spring的应用程序,它封装了很多常用的配置,简化了开…

小程序-基于java+SSM+Vue的校园水电费管理小程序设计与实现

项目运行 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…

前端面试准备问题2

1.防抖和节流分别是什么,应用场景 防抖:在事件被触发后,只有在指定的延迟时间内没有再次触发,才执行事件处理函数。 在我的理解中,简单的说就是在一个指定的时间内,仅触发一次,如果有多次重复触…

【Linux】shell脚本二

2、接收用户的参数 shell脚本已经内设了用于接收用户输入参数的变量,变量之间可以使用空格隔开。 如:./test.sh one two three four $0:对应的是当前shell脚本程序的名称,即test.sh$#:对应的是总共有几个参数&#…

【机器学习】机器学习的基本分类-无监督学习-t-SNE(t-分布随机邻域嵌入)

t-SNE(t-分布随机邻域嵌入) t-SNE(t-distributed Stochastic Neighbor Embedding)是一种用于降维的非线性技术,常用于高维数据的可视化。它特别适合展示高维数据在二维或三维空间中的分布结构,同时能够很好…

二维数组,以及ARRAY的习题及答案

//二维数组 //2.1创建方式1 val arr5 Array.ofDim[Int](2,3)//2行2列 //2.2访问数组的元素 arr5(0)(0)1 arr5(0)(1)2 arr5(1)(0)3 arr5(1)(1)4 //2.3把一维数组转化为二维数组 var arr6 Array(1,2,3,4,5,6) var arr7 arr6.grouped(3)//3个元素一组 // println(arr7)…

Python中的容器化服务监控:结合Prometheus和Grafana实现高效监控与可视化

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代的DevOps和微服务架构中,容器化技术(如Docker)已成为主流的部署方式。然而,容器环境的动态特性使得服务监控和性能分析变得更加复…