分享好友 最新资讯首页 最新资讯分类 切换频道
如何提高web应用的吞吐量
2024-12-29 00:35

如何提高web应用的吞吐量

这篇博文所列举的优化手段是针对比较传统项目,但是想提高系统的吞吐量现在时髦的技术还是那些前后端未分离, 使用nginx当成静态资源服务器去代理我们的静态资源

当我们对一个传统的项目进行压力测试时,很容器就发现,系统的Throughput被数据库(mysql)限制的死死的,尽管代码看起来确实没毛病,逻辑也没有错误,但是过多的请求都被打向了数据库,数据库自个开启大量的IO操作,这样大的负载甚至会使Linux系统的整体负载骤然飙升,但是反观我们的系统的吞吐量,呵呵...

既然mysql的抗压能力限制了我们的系统,那就将数据缓存起来,尽一切可能减少用户和数据库之间的直接接触的次数,这样我们的系统的吞吐量,同一时间能处理器的请求数量自然会升上去

市面上的缓存技术很多, 比较火爆的是两款缓存数据库 Memcache 和 Redis ,

Redis 和 Memcahe的区别

  • Redis不仅仅支持key-value键值对类型的数据,同时还支持list,set,hash等数据结构
  • redis支持数据的备份,即master-slaver模式的集群备份
  • Redis是支持数据持久化的,它可以将内存中的数据保存在磁盘中,支持RDB和AOF两种持久化形式

从上面的压力测试中,可以看到,Redis的性能是绝对实力, 相当强悍,和mysql相比不是一个量级的, 所以结论很明显,如果我们在用户和mysql中键加一层redis做缓存,系统的吞吐量自然会上去

于是为了提高系统的抗压能力,我们将压力从mysql逐步转移到redis中

在说页面缓存之前,我们先说一下在一个传统的项目中,一个请求的生命周期大概是这样的: 从浏览器发出到服务端, 服务端查询数据库获取结果, 再将结果数据传递给模板引擎将数据渲染进html页面

想提高这个过程的速度,我们可以这样搞, 页面缓存, 顾名思义就是将 html 页面缓存到缓存数据库中

示例如下:

一开始我们会先尝试从缓存中获取出已经渲染好的html源码响应给客户端, 响应的格式通过中的属性进行控制,告诉浏览器自己会返回给它html文本

优点: 将用户的请求的压力从mysql转移到redis, 这点强度对redis单机来说根本不是事

缺点: 很明显,将请求扩大到页面级别,数据一致性难免会受到影响, 这也是使用页面缓存不得不考虑的一点

特点1 : 严格控制缓存的时间, 一定别忘了添加过期时间...

特点2 : 原来都是让thymeleaf自动完成数据的渲染,现在的话,很明显是我们手动在渲染数据


既然都说到这里了, 就接着说还能怎么玩吧...

你看, 上面通过手动控制模板引擎的api竟然得到的已经渲染好的html源代码了, 什么叫做已经渲染好的? 说白了就是原来我在前端写:th ${user},这样的占位符,现在已经被thymeleaf替换成了 张三 ... (说的够直接吧)

拿到了已经渲染好的源代码,我们就能通过IO操作,将这个文件写到系统的某个目录上去,不知道大家有没有发现,去逛京东淘宝浏览某个商品页面时,就会发现url是类似这样的 www.jjdd.com/aguydg/ahdioa/1235345.html

这个后缀123145.html 大概率说明京东使用静态页的技术, 这太明智了,面对如此巨大数量的商品信息后缀用数字来表示也不错,而且速度还快不是?

怎么实现这种效果呢?

就是上面说的,通过IO将这些源码的数据写到Linux中的某一个目录下面, 文件名就是上面URL中的最后的数字, 通过Nginx做静态资源服务器将这些xxx.html代理起来, 用户再访问的话就走这个静态页, 同样不会接触数据库, 而且nginx还支持零拷贝,并发数5万不是事...
还有,后缀数组最好也别乱写,直接使用商品id会更好,毕竟是先点击商品获取到id,再进入到静态页

缓存java中的对象, 比如将用户的信息持久化进redis, 每次用户查询自己的信息先从redis中查询,有的话直接返回,没有的话再去查询数据库, 这样同样实现了在用户和数据库之间多添加出一层缓存,也可以大大的提高系统的吞吐量

一般会怎么玩呢?

用户的请求在查询数据库之前先尝试从redis中获取对象信息, redis中不存在的话就去数据库中查询, 查询完结果后将这个结果换存进redis


当用户update数据 ,先更新数据库,再删除/更新redis中响应的缓存


当用户删除数据,先删除数据库中的数据,再删除redis中的缓存



大家都在说页面静态化, 它真的有那么神奇吗? 其实也没有那么神奇, 说白了吧,传统的网页上的数据是通过模板引擎渲染上去的,(比如JSP或者是说thymeleaf这类模板引擎), 做了静态化的网页中数据的渲染通过js完成, 而且这个网页和项目中的 静态资源比如js,css 这类的文件放在一个目录下面, 地位和普通的静态资源相同, 还有个好处就是, 浏览器给的福利, 因为浏览器对静态资源是有缓存的, 如果你善于观察,就会发现有时候重复请求某个网页,网页正常显示,但是状态码是304... 请求依然会到达服务端,但是服务端会告诉浏览器它想访问的页面其实没有变化, 于是浏览器就找到本地的缓存使用

时下国内 最火爆的玩静态页面时下最火爆的技术就是 Angular.js 以及 Vue.js , 也确实好用, 前几个月我写过有关vue的笔记, 感兴趣的同学可以去看看 点击查看我的vue笔记

在本篇博客中恰恰好没用到VUE, 但是实现静态页的思路和vue是大差不差的, 同样是通过js代码实现页面的静态化

  • 首先说后端的代码怎么写?

前后端分离嘛, 自然是json交互,后端通过控制返回给前端json对象, 而且, 推荐大家也整一个VO对象,用这个VO对象将各式各样的数据封装在一起,一次性返回给前端, 这样看上去,后端确实是简单,也就是返回一个json对象

  • 前端怎么写呢?

第一件事就是将html文件从template文件夹下move到static文件夹下面, 让这个html文件和js/css文件称兄道弟

然后是给这个xxx.html该名字, 为啥要改名换目录呢? 因为SpringBoot是约定大于编码的, 在什么目录下面就是什么文件, 此外Thymeleaf部分默认的配置信息如下


没办法,这些配置信息默认就认为类路径下的templates中都是xxx.html的文件

第二件事是将html标签中引入的类似thymeleaf这中命名空间都去掉,静态页不需要


第三件事写一个ajax,当页面一加载就触发向后台发请求,获取数据, 通过jQuery操作各个节点完成数据的渲染

三步打完收工, 看上也不是很复杂, 但是我们的页面就是已然成为了静态页面, 从此她会被浏览器缓存起来,只要这个页面不发生变动,浏览器就会一直使用自己的缓存,在网络上的数据传输量有多带劲自己脑补,系统RT绝对飙升几个数量级

说一下市面上常见的静态资源优化技术吧:

  • js/css 的压缩与优化,减少流量
  • 多个js/css组合在一起,减少连接数量
  • Tengine 技术
  • webPack , 使用vue开发时,它就会将一整套vue的依赖打包一个js一个html文件,岂不是爽歪歪?
  • CDN加速技术, 很多云服务厂商都有提供,而且价格也不贵,将体型大的静态资源放在CDN上进行加速也是不错的选择
  • 使用Nginx做静态资源代理,而且Nginx就支持零拷贝,还支持将数据文件压缩后在网络上传输 ,自身的并发量也很强大,当静态资源服务器它绝对是不二首选, 相信我,你会爱上它的

另外当多个用户并发修改库存时,竟然将库存修改成了负数, 本身使用的数据库引擎是 innodb是存在行级锁的, 我们只要修改一下我们的sql就行 加条件 and stock_number > 0

为了防止同一个用户发送两次请求,偶尔秒杀到多个商品的情况,我们去miaosha_user表中去建立一个唯一的索引,将userId建立唯一索引,不允许相同的userId出现两次,从而避免上述的情况

  • 好处

让用户去输入验证码的好处有很多, 除了验证用户的身份信息之外, 最明显的好处就是分散用户对系统的压力, 前端如果不添加图片验证码的可能在1s内系统需要承载1万并发, 但是添加了图片验证码, 就能将这1万并发分散到10秒以内,甚至更多

  • 整体的思路:

    图片验证码不过是个image, 所以说前端想展示它,肯定需要一个img标签, 一个比较不好想的地方是啥呢? 就是这个图片的路径,src=啥的问题, 我们可以怎么做呢? 可以直接通过这个往src中写入后端的生成imge的Controller的路径, 每次刷新页面,它就会往这个路径中发起请求, Controller中去生成一个image, 通过HttpServletResponse的获取到输出流, 将生成的图片用流的发送会浏览器,再加上他是img标签,这不就ok了?

百度一下如何生成图片验证码一类的技术,确实真的很多,我就不贴代码了, 感兴趣的同学自行百度,代码一片片的

  • 如何实现点击图片完成刷新操作呢?

因为这种图片是静态资源,如果你不禁用缓存,这个图片就会被缓存下来, 要想每次点击图片都实现更换验证码的话,参考下面的js实现, 添加时间戳



  • 什么是接口限流?

举个例子: 如说我们想限制在一分钟内单个用户访问 A Controller中的a方法的次数不能超过30次, 这其实就是一种接口限流的需求, 可以有效的防止用户的恶意访问

  • 如何实现接口限流呢?

其实这件事结合缓存来实现并非是一件难事,比如我就用上面的例子: 不是想对a方法进行限流吗? 我们就在a方法中添加下面的逻辑

伪代码如下:


  • 如何不让限流的逻辑侵染业务代码呢

我们可以使用拦截器技术, 如果我们的重写了拦截器的方法,它就会在执行Controller中的方法前进行回调, 再配合自定义注解技术, 后面简直就是为所以为...

示例:


结语: 最近又到考试周了,今个周六,下周三考试运筹学... 希望自己能平安度过...

我是bloger 赐我白日梦, 欢迎点赞支持

最新文章
安信可分享 | 分享一个基于airkiss协议的配网小程序,实现小程序一键配网安信可ESP32C3\ESP8266\ESP32\ESP32S2系列的模组。(附带源码)
开源项目地址开源时间微信小程序连接mqtt服务器,控制esp8266智能硬件https://github.com/xuhongv/WeChatMiniEsp82662018.
WordPress页面链接添加.html后缀
默认WordPress页面不能实现伪静态链接,比如:https://zmingcx.com/begin.html,手动在链接中添加“.html”,会自动转码为"-html
解读最新权威榜单,全国师范大学排名2019最新排名出炉!
摘要:根据最新发布的2019年全国师范大学排名,本文解读了教育领域的权威榜单。该排名涵盖了多所著名的师范大学,反映了我国教育
日本代码亚洲精品代码网站老牛:揭秘老牛平台提供的高质量编程资源与学习机会
在如今互联网高速发展的时代,编程技能已经成为了许多人不可或缺的一项能力。而日本作为全球科技强国之一,其在编程技术和学习资
Yandex:如何成为俄罗斯互联巨头并挑战全球搜索引擎市场的霸主
Yandex,作为俄罗斯最大的搜索引擎之一,其在全球互联网格局中占据了举足轻重的地位。自1997年成立以来,Yandex不仅仅是一个搜索
微信7.0.2版本 v7.0.2
微信7.0.2版本的运行稳定,功能几乎也是全覆盖的,让很多小伙伴在这里体会到了便利的社交平台,同时语音视频都不是问题,该版本
马斯克再次登顶全球“首富”:与性格里的恶魔做斗争是他一生的主题
埃隆·马斯克,这位科技界的“摇滚明星”,每一步都吸引着全世界的目光。12月13日,根据彭博社亿万富翁排行榜的实时数据,马斯克
游戏开发工程师岗位职责
岗位职责: 1、使用游戏引擎(LayaBox或Egret)完成H5游戏的前端开发,配合后端研发完成游戏的上线; 2、负责解决多浏览器的兼容
超火爆的伦理电影推荐,快来看看第5008页的搜搜搜影院!最新伦理片在线观看热门电影排行榜第5008页搜搜搜影院
最新伦理片大全为观众提供了丰富多样的观看选择,涵盖了不同主题和风格的影片。这些电影不仅探讨了人性、爱情和道德 dilemmas,
星图一周资讯:抖音商城年货节将于2025年1月2日开启
​​星图数据通过公开渠道收集、整理了2024.12.9~2024.12.15的相关行业资讯。​英伟达涉嫌违反反垄断法,市场监管总局依法决定立