接口优化从哪些方面入手?

2023-11-16

关注公众号【1024个为什么】,及时接收最新推送文章!

1、背景

新接手的一个服务,对整个服务熟悉后,发现调用量 TOP1 的一个接口,完全超乎我对这个接口使用场景的预期,预期几万的接口,实际调用量近 400万,和调用方交涉后,暂时无法推动调用方优化,所以只能从接口内部优化。

2、存在的问题

2.1 不合理的重复调用

同一调用链内,连续调用3次

貌似还有定时任务10分钟一次

2.2 日志文件过大,浪费磁盘空间且不利于排查问题

24G,一个下游且相对边缘的服务,单节点的日志竟然 24G,除上游不合理的调用量外,肯定有日志打印不当的地方。

排查问题时搜索到关键字要几十秒,严重影响到问题排查。

2.3 接口平均耗时高

平均耗时 11.5ms,其实内部调用逻辑很简单,就是数据库查询、redis、RPC调用,按调用链路预估 6ms 左右就正常。

2.4 冗余的数据库调用

接口内 18 次数据库调用中,很多是冗余的,可以优化或者减少调用。

2.5 缓存使用不当

redis 调用 8 次,有6次都是重复调用;

缓存内容不合理,缓存了很多无用内容,无需缓存的也用了缓存

3、从哪里入手?

3.1 减少数据库调用、低效查询

1)有一个 2 次单表组合查询的逻辑,接口中总共会调用 3 次。

select * from A where id=?; // 其中包含 B.id
select * from B where id=?;

把 B 中的 amount,覆盖掉 A 中的 amount,返回。

优化为联表查询,都会走主键索引,少一次数据库查询。

2)3 次调用中,最后一次查询是重复的,在第二次查询处理后已经返回了最新的数据,去掉这次查询,直接把第二次返回的数据给第三次查询后的逻辑使用,减少一次数据库查询。

3)有一次提前的无用的数据库查询,查询结果只在后续逻辑特定条件分支才会用到,概率极低,绝大多数会提前返回结果。把这次查询后移到真正使用处,减少一次数据库查询。

3.2 减少 redis 调用

有一个场景,从根据品类ID从缓存获取归属业务线ID的,实际只会有 3 个品类ID,映射出 2 个业务线ID,完全没必要走缓存,直接改为写死返回,可以减少 6 次 redis 调用。

3.3 修改不合理缓存

有一个缓存商家标签的缓存,会缓存标签集合的所有属性,而逻辑中只需要用到标签ID,改为只缓存标签ID,缓存内容减少为原来的 0.8%,节省 redis 缓存,减少网络耗时。

3.4 增加接口缓存

前面提到调用方存在不合理的调用,一次调用链中,连续多次调用,几次的入参、结果都相同,所以没必要每次都走一遍接口逻辑。

对接口层面加缓存,后面几次的访问直接从缓存获取。

由于接口返回内容仅有 200 个字符左右,缓存时间为 2 秒,QPS 为 50 左右,占用缓存空间很小 30K 左右。

3.5 减少不合理的日志

梳理发现,有很多不合理的日志,总结为以下几点:

1)直接把全量集合内容直接打印出来

改为只打印 size,或者只打印关键ID。

2)DAO层冗余的日志

4f4ecc203a359fd4dd9fc7a3afd058bd.png

每行日志除了我们要打印的信息外,还有额外的信息,例如时间、日志级别、调用链、当前位置 等等。

对于实际日志内容很短的场景,很不划算,把 2 行改为 1 行,可以减少很多日志输出。

原则是既不影响排查问题,又不多打无用的日志。

3)低效的日志

正如上图所示,要打印的对象,一律都加了 JSON.toJSONString(),json 框架内部会有很长的调用逻辑,严重影响性能。

删除String 以及基础数据类型的 toJSONString 的转换。

4、效果

优化前耗时:

392756f0082652c98cd9851ddcc8aca5.png

优化后耗时:

85f0a951805fb74308d00ff38645ff1d.png

日志大小:

从 24G 减少到 4 G。

5、总结

我的格局很小,

会抠每一行日志,

会抠整个调用链路上有无重复的查询,

会抠是否需要缓存,

会抠缓存的内容是否都是必要内容,

会抠每一次 rpc 调用是否必要,是否可以缓存。

扯两句

你的问题背景肯定和我的不一样,但可以参考我的思路,死抠每一行代码。

我始终相信,每一个细节都把控好了,就不可能有低效的接口。

原创不易,多多关注,一键三连,感谢支持!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

接口优化从哪些方面入手? 的相关文章

  • JPA 中的复合键

    我想创建一个具有自动生成的主键的实体 而且还有一个由其他两个字段组成的唯一复合键 我如何在 JPA 中执行此操作 我想这样做是因为主键应该用作另一个表中的外键 并且使其复合并不好 在下面的代码片段中 我需要命令和模型是唯一的 pk当然是主键
  • 如何将 javax.persistence.Column 定义为 Unsigned TINYINT?

    我正在基于 MySQL 数据库中的现有表创建 Java 持久性实体 Bean 使用 NetBeans IDE 8 0 1 我在这个表中遇到了一个字段 其类型为 无符号 TINYINT 3 我发现可以执行以下操作将列的类型定义为 unsign
  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • JVisualVM/JConsole 中的 System.gc() 与 GC 按钮

    我目前正在测试处理 XML 模式的概念验证原型 并围绕一个非常消耗内存的树自动机外部库 我已经获得了源代码 构建 我想绘制 真实峰值 堆 随着模式大小的增加 不同运行的内存消耗 使用的指标符合我的目的并且不会影响问题 或者至少是它的合理近似
  • 使用 GWT 读取非常大的本地 XML 文件

    我正在使用 GWT 构建我的第一个 Java 应用程序 它必须从一个非常大的 XML 文件中读取数据 当我尝试发送对文件中信息的请求时遇到问题 并且我不太确定它是否与文件的大小或我的语义有关 在我的程序中 我有以下内容 static fin
  • Java:在 eclipse 中导出到 .jar 文件

    我正在尝试将 Eclipse 中的程序导出到 jar 文件 在我的项目中 我添加了一些图片和 PDF s 当我导出到 jar 文件时 似乎只有main已编译并导出 我的意愿是如果可能的话将所有内容导出到 jar 文件 因为这样我想将其转换为
  • Spring Boot自动装配存储库始终为空[重复]

    这个问题在这里已经有答案了 每次我进入我的服务类时 存储库似乎都没有自动连接 因为它不断抛出 NullPointerException 谁能帮我检查一下我缺少什么吗 这是我的代码 演示应用程序 java package com exampl
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何在代理后面安装 Eclipse Neon

    对于 Neon Eclipse 附带了一个安装程序 我在安装程序中找不到任何配置菜单 我的java版本是 java version java version 1 8 0 72 Java TM SE Runtime Environment b
  • 如何使用 Hibernate (EntityManager) 或 JPA 调用 Oracle 函数或过程

    我有一个返回 sys refcursor 的 Oracle 函数 当我使用 Hibernate 调用该函数时 出现以下异常 Hibernate call my function org hibernate exception Generic
  • 了解joda时间PeriodFormatter

    我以为我明白了 但显然我不明白 你能帮我通过这些单元测试吗 Test public void second assertEquals 00 00 01 OurDateTimeFormatter format 1000 Test public
  • 如何在 Spring 属性中进行算术运算?

  • 读取电子邮件的文本文件转换为 Javamail MimeMessage

    我有一个电子邮件原始来源的文本文件 直接从 gmail 复制 如果您单击 查看原始文件 您就会看到它 我想读入该文件并将其转换为 MimeMessage 如果您好奇为什么 我设置了 JavaMaildir 并且需要用电子邮件填充它的收件箱以
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • 使用按钮作为列表的渲染器

    我想使用一个更复杂的渲染器 其中包含列表的多个组件 更准确地说 类似于this https stackoverflow com questions 10840498 java swing 1 6 textinput like firefox
  • 如何使用play框架上传多个文件?

    我在用play framework 2 1 2 使用java我正在创建视图来上传多个文件 我的代码在这里 form action routes upload up enctype gt multipart form data
  • 在浏览器刷新中刷新检票面板

    我正在开发一个付费角色系统 一旦用户刷新浏览器 我就需要刷新该页面中可用的统计信息 统计信息应该从数据库中获取并显示 但现在它不能正常工作 因为在页面刷新中 java代码不会被调用 而是使用以前的数据加载缓存的页面 我尝试添加以下代码来修复
  • Java EE 目录结构

    我对以下教程有疑问 http www mkyong com jsf2 jsf 2 internationalization example http www mkyong com jsf2 jsf 2 internationalizatio
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐

  • 华为OD机试真题 Java 实现【字符串加密】【2023Q1 100分】,附详细解题思路

    一 题目描述 有一种技巧可以对数据进行加密 它使用一个单词作为它的密匙 下面是它的工作原理 首先 选择一个单词作为密匙 如TRAILBLAZERS 如果单词中包含有重复的字母 只保留第1个 将所得结果作为新字母表开头 并将新建立的字母表中未
  • 闭环系统的零极点图判定稳定性_三步教你设计运放电路稳定性

    1 前言 集成运算放大器的参数有很多 但涉及到实际应用环境的不同 一些参数非常重要 另外一些则相对次要 例如 在交流高频领域 会重视带宽和压摆率 而在直流精密场合 则重视输入失调电压 输入偏置电流 还有一些参数 不管直流还是交流 都会重点关
  • 清华大学开源的chatGLM-6B部署实战

    Windows部署 win10 通过wsl部署 常见问题 torch cuda OutOfMemoryError CUDA out of memory 在Windows的系统环境变量中增加 变量名 PYTORCH CUDA ALLOC CO
  • 通过alter table A engine=innodb来重建表

    1 业务场景 即为什么要重建表 由于前期的存储设计不合理 表里有个字段 用于存储大段字符串 导致存储到磁盘的空间极大 严重影响表相关的增删改查速度 所有需要对表存储设计进行重构 并对表进行重建 2 实践记录 我们业务场景是由软删字段的 de
  • C++,类的多态

    一 多态的基本概念 多态 父类的指针或引用 指向或初始化子类的对象 调用子类对父类重新的函数 进而展开子类的功能 函数重新的必要条件 必须有继承关系 子类和父类有同名同类型的函数 父类中的该函数必须是虚函数 虚函数 在函数前加上virtua
  • K8s Kubernetes集群部署

    root master yum y install docker ce root master systemctl enable now docker Created symlink etc systemd system multi use
  • QT取消标题栏,如何实现窗口移动

    qt自带的标题栏在多个平台都显示的不一样 而且在常用的window平台也非常的不好看 所以我们经常会用到的美化方式就是会取消标题栏的显示 但是取消标题栏的显示就会出现一个问题就是无法实现窗口的移动 所以这里给出一个方法实现左键按压窗口控件任
  • MATLAB算法实战应用案例精讲-【异常检测】OCSVM算法(附Python和MATLAB代码)

    目录 前言 几个高频面试题目 1 OneClass 与二分类 多分类的区别
  • 计算机体系结构基础知识介绍之缓存性能的十大进阶优化之非阻塞缓存(四)

    优化四 非阻塞缓存 提高缓存带宽 对于允许乱序执行的流水线计算机 处理器不需要因数据高速缓存未命中而停止 例如 处理器可以继续从指令高速缓存获取指令 同时等待数据高速缓存返回丢失的数据 非阻塞高速缓存或无锁高速缓存允许数据高速缓存在未命中期
  • 继承中方法的覆盖重写_概念与特点,

    重写 Override 概念 在继承关系当中 方法的名称一样 参数列表也一样 重写 Override 方法的名称一样 参数列表 也一样 覆盖 覆写 重载 Overload 方法的名称一样 参数列表 不一样 方法的覆盖重写特点 创建的是子类对
  • 必刷算法题之字符串(题目及代码)---C++

    文章目录 第1题 执行操作后的变量值 第2题 罗马数字转整数 第3题 句子中的最多单词数 第4题 左旋转字符串 第5题 宝石与石头 第6题 Excel 表中某个范围内的单元格 第7题 括号的最大嵌套深度 第8题 分割平衡字符串 第9题 最长
  • CACC 协同式自适应巡航模型 搭建四辆车在carsim和simulink进行协同式自适应巡航 其中间距策略考虑领航车速的影响,各个车辆采用分层式控制,分层式控制器主要分为下层控制

    CACC 协同式自适应巡航模型 仿真软件版本 Carsim2016 Matlab2018b及以上 搭建四辆车在carsim和simulink进行协同式自适应巡航 其中间距策略考虑领航车速的影响 各个车辆采用分层式控制 分层式控制器主要分为下
  • ubuntu 22.04 安装 Docker Desktop 及docker介绍

    目录 一 Docker Desktop 安装 1 我们先去官网下载安装包 2 Install Docker Desktop on Ubuntu 3 Launch Docker Desktop 二 Docker 介绍 什么是docker 如何
  • 启动mongodb数据库 mongo命令时回报计算机拒绝访问

    当你没有启动mongodb数据库的时候 bin目录下输入mongo命令时回报计算机拒绝访问 这个时候解决办法是进入bin目录输入mongodb exe dbpath c data db dbpaht 后面一定要加 双引号 否则会报错误
  • NODE.JS--如何使用Node.js

    简单的说 Node js 就是运行在服务端的 JavaScript Node js 是一个基于Chrome JavaScript 运行时建立的一个平台 Node js是一个事件驱动I O服务端JavaScript环境 基于Google的V8
  • vscode remote server tunnel内网穿透转发tcp,速率10kb每秒

    参考 vscode网页版的正确打开方式 建立tunnel p2p连接 vscode打开网页 怪力左手的博客 CSDN博客 vscode内网穿透 白嫖10M带宽穿透 remote tunnels远程开发插件 不嫖白不嫖 哔哩哔哩 bilibi
  • 深入浅出的讲解傅里叶变换

    作 者 韩 昊 知 乎 Heinrich 微 博 花生油工人 知乎专栏 与时间无关的故事 谨以此文献给大连海事大学的吴楠老师 柳晓鸣老师 王新年老师以及张晶泊老师 转载的同学请保留上面这句话 谢谢 如果还能保留文章来源就更感激不尽了 其实学
  • Ubuntu 安装 CUDA(附测试)

    为深度学习所用 博主预想在Ubuntu16 04上安装 显卡驱动 CUDA cuDNN Tensorflow gpu Keras PyCharm 参考了众多资料 最终成功将所有软件安装完毕 且能成功运行使用 该篇博客介绍了CUDA的安装教程
  • 2023-详解实时数仓建设

    一 实时数仓建设背景 1 实时需求日趋迫切 目前各大公司的产品需求和内部决策对于数据实时性的要求越来越迫切 需要实时数仓的能力来赋能 传统离线数仓的数据时效性是 T 1 调度频率以天为单位 无法支撑实时场景的数据需求 即使能将调度频率设置成
  • 接口优化从哪些方面入手?

    关注公众号 1024个为什么 及时接收最新推送文章 1 背景 新接手的一个服务 对整个服务熟悉后 发现调用量 TOP1 的一个接口 完全超乎我对这个接口使用场景的预期 预期几万的接口 实际调用量近 400万 和调用方交涉后 暂时无法推动调用