【架构】客户端优化

news2025/1/23 22:28:54

这篇文章总结一下服务器网关及之前部分的优化,如客户端的优化,CDN/DNS等。

这里我们先谈一谈客户端缓存优化的手段。一般我们后端在说到缓存,第一时间想到的往往是redis,其实缓存在架构层次还有很多其他可以实现的地方,如客户端缓存。对不同的场景,我们可以尝试不同的客户端优化手段。

1,资源下载

压缩资源:对资源进行压缩,如某些业务场景,不需要展示全像素的图片,可以图片压缩成缩略图,存储在文件系统中,前端需要时,将缩略图传输给前端进行展示,只有在必要时,才会将全像素的原图传输给前端。或者如我们在下载某些资源时,常常是zip格式,这也是对资源进行压缩的表现。

删除不必要的cookie:浏览器第一次访问服务器时,会生成一个session对象保存在服务器中,浏览器中保存sessionId作为查询用户信息的凭证[1,2],而浏览器在访问服务器时,将sessionid放在了cookie中。对于开发来说,有时候经常会随手携带上cookie。但其实对于接口不需要的session和cookie的,我们可以不用带上cookie,避免带宽的占用。

js删除无效字符和注释:这个的作用有两个,1是降低体积。2是为了代码安全,防止代码被轻易理解,进而对于服务器的恶意攻击。

css压缩:类似js压缩。1是删除注释,无效的字符、空格、回车。可以借助压缩网站进行压缩[3]。2是样式的语义合并

http请求压缩:head中加参数:Accept-Encoding:gzip,deflate,表示 客户端 可以接受的压缩内容的格式,客户端接收到数据后可以以这种格式进行解压;服务端响应时,在head中加参数: Content-Encoding:gzip,并在服务端手动做一些压缩的操作。

此外由于这种方式浏览器需要等待服务器将数据压缩完再发送给浏览器,等待时间长。因此往往配合transfer-encoding:chunked来使用,服务器将会把数据分块压缩并直接传输给浏览器,浏览器不用等待所有数据都压缩完再解压[4]。

将多个小图标合并为雪碧图(CSS Sprite, CSS精灵):如官网边缘常常显示多个小图标,这种小图标如果每个都单独请求接口,对于网络的压力会更大。可以使用这种叫做雪碧图[5,6]的技术,将多个小图标合并为雪碧图,可以减轻后端网络的压力。前端通过指定background-position来指定小图标坐标。

前端 < svg >生成矢量图代替后端直接传输矢量图图片:< svg >可以用于生成矢量图[7],这种生成的矢量图可以无限放大而不失真,同时后端也只用传输矢量图的数据而不是图片本身,减小了网络压力。

js文件合并打包:将多个js文件合并为一个文件,便于下载。

使用base64编码对图片进行转换后再压缩:如果图片不适用前面直接对图片压缩为缩略图的方式,可以使用这种方式,先使用base64将图片转换为字符串,再使用压缩算法对字符串进行压缩。客户端那里反向解压再转换回图片。如一篇文章[8]中举例,使用base64编码后,字符串大小和图片本身差不多大。再使用gzip压缩,压缩率可达50%以上。

转移第三方:将文件系统的压力转移给第三方,如阿里云OSS服务。

2,资源缓存优化

资源缓存是对资源下载的优化之一,但是客户端缓存的优化比较复杂,这里单独拆出来讲。通俗的说,资源缓存有客户端缓存/页面缓存,代理服务器缓存/CDN缓存,这些缓存并不是孤立存在,经常是同时存在的。此时需要前端与后端一起对缓存进行控制,如下所述。

客户端/页面缓存 & CDN/代理缓存[13]:控制 客户端、各级代理(中间的各个节点),对页面资源的缓存。请求头中添加Cache-Control,有些参数是客户端请求时添加的缓存请求指令,有些参数是服务端响应时添加的缓存响应指令,列举参数如下[13]:

缓存策略

//public和private是服务器做响应时添加的参数才能生效。
pubic(服务器 响应): 各级都能缓存。

private(服务器 响应): 只能 客户端 缓存,中间各级不缓存,默认就是private。

no-cache: (请求,响应):可以缓存,但是不能直接使用缓存,要去服务端验证一下(即缓存协商)。

no-store: (请求,响应):哪都不要存。

缓存有效期

max-age=秒(服务器 响应),缓存可以存活的相对时间。

s-maxage=秒(服务器 响应),在各级cache服务器(CDN,代理服务器[14])存活的时间,仅在为public缓存生效,如果是客户端缓存忽略。

max-stale=秒(客户端 请求),可以忍受从代理服务器拿缓存资源过期的时间。

min-fresh=秒(客户端 请求),需要的代理服务器缓存资源的新鲜度,即要求代理服务器的缓存资源至少要在过期时间之前min-fresh秒才可以使用和获取

重新验证和加载的设置

must-revalidate(服务器 响应)[15]: 资源过期后,服务器重新验证之前,不可以使用该资源。

proxy-revalidate(服务器 响应): 作用与must-revalidate类似,但是仅对各级缓存节点有效,对客户端私有缓存无效。

no-transform(服务器 响应): 不允许代理对资源格式如Content-EncodingContent-RangeContent-Type进行改变,因为如非透明代理或者如Google's Light Mode可能对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。

only-if-cached(客户端 请求): 只要各级代理服务器与CDN的资源,不要服务器的资源,也不需要检查服务器资源的更新。

使用缓存,就可能存在缓存导致的一致性问题。源站更新了缓存,CDN或者代理服务器如何保证一致性呢?

对于CDN,比如阿里云提供的CDN[16],提供了刷新功能。在调用CDN服务提供商的刷新API接口后,CDN会刷新缓存节点中的数据,大约五分钟左右生效,这段期间,会将请求路由给源站。

在这里插入图片描述
在这里插入图片描述
对于代理服务器,如nginx,ATS,则没有这么智能了。那它们如何解决一致性问题呢?

(1),更新文件名
更新的文件名可以根据版本号或url时间戳的变化而变化,如my.js,my-1.js。这种方案要求客户端和服务器要达成一致,那么客户端请求代理服务器时,查不到新名字的资源,就会被路由到源站进行资源的查询与资源刷新,旧名字的资源超时后被代理服务器删掉。

(2),协商缓存验证缓存有效性
前面讲过一个叫做缓存协商的策略(Cache-Control:no-cache),即查询到CDN/代理缓存后,不会直接返回客户端,而是去服务器验证有效性再返回客户端。

协商缓存主要有四个头字段,它们两两组合配合使用,Last-ModifiedIf-Modified-Since 一组验证修改时间,EtagIf-None-Match 一组验证版本号,当同时存在的时候会以 EtagIf-None-Match 为主。当命中协商缓存的时候,服务器会返回HTTP状态码304,让客户端直接从本地缓存里面读取文件[13],未命中协商缓存,会从服务器返回具体资源,状态码200。

修改时间:

If-Modified-Since:请求头,当前缓存资源最近修改时间,由浏览器告诉服务器。其实就是第一次访问服务端返回的Last-Modified的值。

Last-Modified:响应头,服务器中资源最近修改时间,由服务器告诉浏览器。

版本号:

If-None-Match:请求头,缓存资源标识,由浏览器告诉服务器。其实就是第一次访问服务端返回的Etag的值。

Etag:响应头,资源标识,由服务器告诉浏览器。

3,客户端连接优化

http长短连接:http1.0仅支持短链接,不支持长连接,而现在的http协议大多至少为http1.1协议是支持长连接的。需要注意的是,http协议是基于请求/响应模式的协议,不管是长连接还是短连接都是响应结束就关闭。http协议中的长短连接,是指的是否复用OSI七层模型中传输层的tcp协议[9],即http长连接中,请求响应结束后,一段时间内,tcp协议不会关闭,等待http协议复用tcp协议。而短连接则是每次都会三次握手建立新的tcp连接,并且再结束时四次挥手。

http1.1建立长连接,在请求头中加入Connection:keep-alive即可,Keep-Alive: timeout=60表示超时时间为60秒[10]。

长轮询与短轮询:准确得说,长轮询是服务端的一种模式。我们平时的服务端,收到客户端的请求,去查询数据,不管查到与否,会直接将响应返回。这个是短轮询,也就是轮询[11](客户端轮询查询服务器),这种方式实现简单,但是对于需要多次频繁请求的业务场景,往往会对服务器造成很大的压力。这时服务端可以使用长轮询[11],即服务端阻塞一段时间,在数据有变化了以后,再将数据返回给客户端,或者直到请求超时返回。在阻塞的这段期间,可以使用redis的pubsub订阅发布或者MQ来接收数据变化的通知。或者使用循环,阻塞指定时间后查询数据库,直到超时或有数据更新。

双工通信:对于客户端轮询服务端造成的网络开销问题,也可以使用Netty来实现一个websocket服务,websocket是一个基于tcp协议的双工通信协议[12],即可以客户端给服务端发信息,也可以服务端给客户端发信息。这里可以客户端每隔一段时间给客户端发请求,也可以服务端数据变化发给客户端。具体的要看业务。

双工通信与长轮询的区别在于,长轮询由服务器控制,而双工通信,客户端和服务端是平等的。相同点是都可以减小网络连接与销毁的开销。

4,优化加载顺序

懒加载:仅仅加载 最基础的元素,以后再根据用户的操作,进行局部加载。将原来一次性要加载的内容拆分成了多次加载,目的在于将数据进行分流,常见于h5/app界面、树形组件、折叠面板、标签页等。
使用时尽量灵活一些,支持多种情况。到了不得不看具体数据的时候,才调用后端。但是上述场景是否使用懒加载是不一定的,对于一些经常不变的数据,就没必要了,一切要以适合业务为准。

预加载

1.同一个域名下,

预加载拉取资源[17],

#告诉浏览器立即加载资源
<link rel="preload" href="xxxx.js" />
#告诉浏览器空闲时再加载资源
<link rel="prefetch" href="xxxx.js" />

如在一些小说网站的下一页会使用预加载,刚进入页面时下一页的页码是灰色的,过几秒变成了绿色的,代表此时预加载完成,可以提高用户的体验。

2,不同域名下,

打开浏览器的dns预解析[18],

<meta http-equiv="x-dns-prefetch-control" content="on">

设置dns解析目标

#使用不完整的url域名解析,这些域名前要加//[18]。
<link rel="dns-prefetch" href="//www.baidu.com">

预加载拉取资源[17],

#告诉浏览器立即加载资源
<link rel="preload" href="xxxx.js" />
#告诉浏览器空闲时再加载资源
<link rel="prefetch" href="xxxx.js" />

5,客户端数据库

pc客户端可以使用h5支持的html web sql数据库[19],安卓上可以使用sqlite数据库[20],pc浏览器上的web sql如下:

在这里插入图片描述
如在访问百度时,本地存储中存了一些永不过期的数据,会话存储存了一些生命周期为会话级的数据。借助web sql数据库,可以实现更多缓存和存储的操作,减小对于后端的访问量。

6,动静分离

前面讲了客户端缓存,CDN/代理服务器缓存,可能有人会讲,静态数据的缓存不少讲了么,为什么还要讲动静分离呢?这部分需要重申的就是,什么是静态数据,静态数据应该放在哪里?

什么是静态数据?
静态数据不仅包括 传统意义上的页面/图片等,也包括和访问者无关的非个性化数据。

如一篇新闻,假设其和用户推荐无关,那么这篇新闻就可以放入CDN中作为静态数据。

再比如,有时电商网站访问高峰期,猜你喜欢会关闭动态推荐,改为所有用户推荐一样的数据,那么这些数据也可以作为静态数据,放入CDN或代理服务器缓存中。

静态数据应该放在哪里?
放在离客户端最近的地方,包括不限于浏览器缓存、CDN、代理服务器缓存等。

要怎么做?
链接和数据做唯一kv映射,根据url可以直接从CDN获得一个静态数据。如果缓存到了客户端,甚至都不用发http请求了(如下面京东商城的图片)。特殊展示的元素做分离:尽可能的多做静态化。将页面中的cookie,与用户个性化相关的东西去掉。

举个例子,京东商城的产品详情页,如果url定义为www.xxx.com/getItem?itemId=1类似于这种,如此是把产品定义为动态数据,商品数据从后端数据库返回,图片数据要从文件系统服务器查询后返回,如此,商品数据+样式文件,渲染出最终的h5页面。

在业务允许的范围内,我们把如果我们把页面视为静态数据,那么用户可以直接访问h5的url。下面举例京东商城,就是直接把商品详情页链接和数据做映射,直接访问h5资源。
在这里插入图片描述

在这里插入图片描述

而图片是由代理服务器nginx处理返回的,X-Cache-Lookup通常为CDN添加,cache hit表示缓存命中[21]。

在这里插入图片描述
这种方式,最终的目的就是流量的分流,借助CDN和代理服务器,缓解了后端的压力。

先写这么多,后面有再补充。

参考文章:
[1],Session(会话)的三种创建方式
[2],一文讲透Token与Cookie、Session的区别
[3],性能优化: 资源合并与压缩 – 压缩(前端开发过程中 JavaScript、HTML、CSS 文件的压缩)
[4],HTTP 传输内容的压缩
[5],浅谈 CSS Sprites 雪碧图应用
[6],CSS Sprite(雪碧图)简单使用
[7],SVG 教程
[8],Base64详解:玩转图片Base64编码
[9],http的长连接和短连接(史上最通俗!)以及应用场景
[10],HTTP长连接、短连接使用及测试
[11],实现Web端即时通讯的方法:轮询(短轮询)、长轮询(comet)、长连接(SSE)、WebSocket
[12],什么是WebSocket (经常听别人讲感觉很高大上其实不然)
[13],彻底弄懂前端缓存
[14],缓存代理服务器的实现机制和技术选型
[15],Cache-Control
[16],刷新和预热资源
[17],预加载属性 preload 与 prefetch 区别
[18],meta标签属性x-dns-prefetch-control的含义
[19],HTML5 Web SQL 数据库
[20],SQLite 教程
[21],腾讯云 CDN 的 X-Cache-Lookup

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978041.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从LLM到大模型推理的最新进展

大语言模型LLM的推理引擎经过一年时间发展&#xff0c;现在主流方案收敛到了开源的vLLM和半闭源的TensorRT-LLM。 TRT-LLM基于C开发&#xff0c;有NV算子开发黑魔法加持&#xff0c;在其重点支持的场景里&#xff0c;性能可以做到极致。vLLM基于python开发&#xff0c;代码简洁…

MySQL第2讲--关系型数据库以及SQL语句分类之DDL数据库和表的操作

文章目录 前言关系型数据库&#xff08;RDBMS&#xff09;关系型数据库的特点 MySQL数据模型SQL介绍基本语法规则SQL语句的分类DDL的介绍DDL的数据库操作DDL的表操作 前言 上一节MySQL第1讲–详细安装教程和启动方法中介绍了MySQL如何安装&#xff0c;以及如何启动和客户端连接…

使用 Elastic 和 Mistral 构建多语言 RAG

作者&#xff1a;来自 Elastic Gustavo Llermaly 使用 Elastic 和 Mixtral 8x22B 模型构建多语言 RAG 应用程序。 Mixtral 8x22B 是性能最高的开放式模型&#xff0c;其最强大的功能之一是能够流利使用多种语言&#xff1b;包括英语、西班牙语、法语、意大利语和德语。 想象一…

质量属性-系统架构师(四十)

质量属性 1性能&#xff1a; 指系统响应能力。如响应时间、吞吐量。 设计策略&#xff1a;优先级队列&#xff0c;增加计算机资源&#xff0c;减少计算机开销&#xff0c;引入并发机制&#xff0c;采用资源调度。 2可靠性&#xff1a; 在一定时间内正常运行的情况下&#x…

PTA—基础编程题目集(7-21)

7-21 求特殊方程的正整数解 目录 题目描述 输入格式&#xff1a; 输出格式&#xff1a; 输入样例1&#xff1a; 输出样例1&#xff1a; 输入样例2&#xff1a; 输出样例2&#xff1a; 参考代码 总结 题目描述 本题要求对任意给定的正整数N&#xff0c;求方程X2Y2N的…

《Milvus Cloud向量数据库指南》——关于Ivy.ai:重塑沟通效率与数据安全的创新先锋

关于Ivy.ai:重塑沟通效率与数据安全的创新先锋 在数字化转型的浪潮中,Ivy.ai以其前瞻性的视野和专业团队的匠心独运,正逐步成为高等教育、医疗保健及公共部门沟通效率提升的引领者。这家企业不仅代表了人工智能技术在服务领域的最新进展,更以其旗舰产品IvyQuantum™的横空…

搬瓦工香港CMI VPS测评

搬瓦工香港cmi怎么样&#xff1f;搬瓦工香港VPS分CN2 GIA和CMI两种不同接入的网络&#xff0c;其中CMI网络的回程是强制三网全部都走移动CMI线路&#xff0c;相对CN2 GIA来说有一定的差距。实际的情况测评数据送上&#xff0c;可供参考。 CPU型号未知&#xff0c;主频2.7GHz&a…

【C++】一堆数组 冒泡排序

冒泡排序&#xff0c;一种很常见的排序法师 这章要划重点&#xff0c;很重要&#xff01;&#xff01; 排序思路为前一个元素与后一个元素比大小&#xff0c;一直循环一轮&#xff0c;找出最大/最小的那个元素后&#xff0c;进行下一轮&#xff0c;找到第二大/小的元素......…

ZLM推流

ZLM推流 ffmpeg -re -i D:\work\gb28181-client\target\classes\device\videofile.h264 -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000把这个复制出来然后将defaultVhost_改成127.0.0.1

题海战术,面试必胜秘诀

目录 1.Java 的优势是什么&#xff1f;2.什么是 Java 的多态特性?3.Java 中的参数传递是按值还是按引用?4.为什么 Java 不支持多重继承?5.什么是 Java 中的不可变类?总结 题目 来自面试鸭刷题神器 1.Java 的优势是什么&#xff1f; Java 的跨平台性、垃圾回收机制以及其强…

【EtherCAT】Windows+Visual Studio配置SOEM主站——源码配置

目录 一、准备工作 1. Visual Studio 2022 2. Npcap 1.79 3. SOEM源码 二、源码部署 1. 新建Visual Studio工程 2. 创建文件夹 3. 创建主函数 4. 复制源代码 5. 删除无关项 6. 将soem源码添加进工程 7. 添加soem头文件 8. 配置头文件路径 9. 配置静态库和静态库路…

xdma的linux驱动编译给arm使用(中断检测-测试程序)

1、驱动链接 XDMA驱动源码官网下载地址为&#xff1a;https://github.com/Xilinx/dma_ip_drivers 下载最新版本的XDMA驱动源码&#xff0c;即master版本&#xff0c;否则其驱动用不了&#xff08;xdma ip核版本为4.1&#xff09;。 2、驱动 此部分来源于博客&#xff1a;xd…

多模态MLLM都是怎么实现的(12)-Florence-2

最近一直在打艾尔登法环DLC&#xff0c;疏于更新了&#xff0c;罪过罪过&#xff0c;今天把拉塔恩给过了&#xff0c;也该更新了&#xff0c;停更期间&#xff0c;催更的信息主要是啥时候更新GPU系列的第五篇&#xff0c;不是不更&#xff0c;是刚打完&#xff0c;正好有客户要…

C# Unity 面向对象补全计划 七大原则 之 里氏替换

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 本系列作为七大原则和设计模式的进阶知识&#xff0c;看不懂没关系 请看专栏&#xff1a;http://t.csdnimg.cn/mIitr&#xff0c;尤其是关于继承的两篇文章&#xff…

算法022:寻找峰值

寻找峰值. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/find-peak-element/ 这个题跟上一个题很像&#xff0c;也是寻找一个峰值。此题还特意强调了如果有多个峰…

【数学思维培养】罗博深小学数学青少年数学思维分级课程(3-4年级)

【数学思维培养】罗博深小学数学青少年数学思维分级课程&#xff08;3-4年级&#xff09; 背景前摇&#xff1a; 虽然我是学理工科计算机的&#xff0c;但我感觉我在数学方面一直都存在劣势&#xff0c;无论是写程序到了涉及数学计算的地方&#xff08;比如向量、余弦等&#…

【数据分析--带你认识数据分析,了解数据分析的】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索数据分析—基础介绍&#xff0c;本篇文章主要讲述了&#xff1a;数据分析的介绍&#xff0c;Python开源库&#xff0c;配置Jupyter等等。欢迎大家一起探索讨论…

C++程序的编译链接过程

一、预处理 &#xff08;1&#xff09; 将所有的#define删除&#xff0c;并且展开所有的宏定义 &#xff08;2&#xff09; 处理所有的条件预编译指令&#xff0c;如#if、#ifdef &#xff08;3&#xff09; 处理#include预编译指令&#xff0c;将被包含的文件插入到该预编译…

html+css 实现hover边框彩色流动

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…