从输入URL地址到看到页面,到网络性能优化

从输入URL地址到看到页面,中间经历了什么?

  • URL解析
  • 缓存检查
  • DNS解析
  • TCP三次握手
  • 数据传输
  • TCP四次挥手
  • 页面渲染

第一步:URL解析

地址解析

协议默认端口号传输协议
http80超文本传输协议
https443在http的基础上进行了安全设置(SSL/TSL)证书认证
ftp21主要用于客户端电脑和服务器端的文件传输

URL的编码

对于一些特殊字符,我们在客户端和服务器端传递的时候,需要进行解码和编码

  • encodeURI、decodeURI:对中文、空格等编码解码

  • encodeURIComponent、decodeURIComponent:对中文、空格 : / 等编码解码(一般应用于查询字符串中部分参数含有http路径参数等)

  • escape unescape 主要用于客户端不同页面之间的数据传输的时候,信息的编码解码(如:cookie)

第二步:缓存检查

缓存位置: 内存缓存(Memory Cache)、 硬盘缓存(Disk Cache)

  • 打开网页:查找 Disk Cache中是否有匹配,如有则使用,如没有则发送网络请求
  • 普通刷新(F5):因TAB没关闭,因此 Memory Cache是可用的,会被优先使用,其次才是 Disk Cache
  • 强制刷新:(ct+F5浏览器不使用缓存,因此发送的请求头部均带有 Cache-contro: no-cache(为了兼容,还带了 Pragma:no-cache),服务器直接返回200和最新内容

强缓存 Expires/Cache-Control

浏览器对于强缓存的处理:根据第一次请求资源是返回的相应头来判断

  • Expires:缓存过期时间,用来指定资源到期的时间(HTTP/1.0)
  • Cache-Control:cache-contro:max-age=2592000第一次拿到资源后的2592000秒内(30天),再次发送请求,读取缓存中的信息(HTTP/1.1)
  • 两者同时存在的话, Cache-Control优先级高于 Expire

服务器设定了一些“资源(静态资源htmU/css/js/图片)〃"的“强制缓存"机制,在浏览器缓存的有效期内,我们除了清缓存刷新,正常加载页面,都是从缓存中获取数据,而不是从服务器重新获取

  • 优势:减少对服务器的请求,加载资源更快,页面渲染速度更快
  • 弊端:当我们的资源在服务器更新了,但是本地还是有缓存的,这样导致客户端无法及时获取最新的资料,结局方案
    • HTML页面不做缓存,每一次发布资源的时候,内容有更新,资源文件名字都是不一样的 [webpack名字设置HASH],这样页面请求的资源文件也就变了,客户端做过此新文件的缓存,还是从服务器获取
    • 哪怕文件名字不变,只要在请求资源文件的后面加一个时间戳也是可以的,这样也是重新获取,而不是走缓存
    • 不做强缓存的设置,基于协商缓存实现(真实项目中,往往是两者同时设置的)

协商缓存 Last-Modified/ETag

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程

  • 协商缓存生效,返回 304 和 Not modified

  • 协商缓存失败,返回200和请求结果

  • Last-Modified If-Modified-Since

    • 第一次访问资源,服务器返回资源的同时,响应头中设置Last-Modified(服务器上的最后修改时间),浏览器接收后,缓存文件和响应头
    • 下一次请求这个资源,浏览器检测到有Last-Modified,于是添加If- Modified-Since请求头,值就是Last-Modified中的值;
    • 服务器再次收到这个资源请求,会根据If- Modified-Since中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果If-Modified-Since的时小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200
    • 但是Last-Modified只能以秒计时,如果在不可感知的时间内修改完成文件,那么服务端会认为资源还是命中了,不会返回正确的资源
  • ETag和If-None-Match

    • Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成
    • 下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到请求头If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
    • 如果服务器发现ETag匹配不上,那么直接以常规GET200回包形式将新的资源(当然也包括了新的ETag)发给客户端
  • 实际场景

    打包后的静态文件

数据缓存 LocalStorage

页面刷新都先检验本地是否有数据,以及存储的时间是否还在有效期(有效期自己设定):在有效期,直接本地获取数据渲染,如果没有数据或者过期了,重新发送请求,再把获取的最新结果重新存储。

第三步:DNS解析

DNS解析:DNS服务器(域名解析服务器)

  • 部署服务器后,服务器有一个外网IP地址,基于外网工P可以找到服务器
  • 外网IP别人记不住,但是可以记得住“域名”
  • 域名解析服务器DNS:记录了域名主机地址(外网IP)相对应的记录信息www.baidu.com -> 127.0.0.1
  • “DNS解析”就是根据浏览器识别出来的URL地址中的域名,到DNS服务器上,查找服务器外网IP的过程
    • DNS解析也是有缓存的:浏览器解析过一次,一般就会在本地记录一下解析记录
    • 所以每一次DNS解析:本地DNS服务器解析(递归)、根/顶级/权威域名服务器解析(迭代)

每一次DNS解析时间预计在20 ~ 120 毫秒

优化

减少DNS请求次数

页面中尽可能少用过多域名(资源信息尽可能发布在不同服务器上)

服务器部署资源还有更大的好处,服务器使用合理化,HTTP有并发性,但是它的并发性是受到源的限制的,同一个源一次最多并发4~7个;如果我们分开部署,就会存在很多源,同时可以并发的HTTP数量也会增多,所以大公司服务器基本上都市分开部署的(尤其是图片等富媒体资源服务器)

DNS预获取(DNS Prefetch)

在不能減少DNS解析记录的情况下,我们可以把DNS预解析(解析完成先缓存起来)

  • 处理方法
<link rel="dns-prefetch" href="//g.alicdn.com"/>
  • 天猫源代码

第四步:TCP三次握手

  • seq序号,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记
  • ack确认序号,只有AcK标志位为1时,确认序号字段才有效,ack=seq+1
  • 标志位:共6个,即URG、ACK、PSH、RST、SYN、FN等,具体含义如下
    • URG:紧急指针( urgent pointer)有效
    • ACK:确认序号有效
    • PSH:接收方应该尽快将这个报文交给应用层
    • oRST:重置连接
    • SYN:发起一个新连接
    • FIN:释放一个连接

TCP 和 UDP,TCP是客户端和服务端建立连接或者取消连都需要基于三次握手和四次挥手,保证了通信的稳定性,UDP两端建立连接没有那么多处理步骤,直接快速建立,会不稳定(即时通信)

第五步:数据传输

HTTP报文信息

发送数据HTTP Request

  • 起始行,例如:URL、POST / HTTP/1.1
  • 请求头(Headers),例如:AuthorizationLast-Modified
  • 请求主体(body),例如:POST请求传递信息

发送数据HTTP Response

  • 起始行,例如:网络状态码HTTP/1.1 404 Not Found。
  • 响应头(Headers),例如:服务器时间
  • 响应主体(body),例如:客户端需要的信息大部分都在这里

    HTTP 消息报文详解 | MDN

响应状态码

用来表示一个 HTTP 请求是否成功完成。响应被分为 5 种类型:信息型响应,成功响应,重定向,客户端错误和服务端错误。
HTTP 响应状态码详解 | MDN

并发性

第六步:TCP四次挥手


Connection: keep-alive 在第一次通信建立好通道之后(TCP三次握手),服务器端和客户端不会主动关闭通道,这样下一次在发送请求,就无需再次TCP三次握手了,节省了网络通信时间

http1.0中默认Connection并不是keep-alive,需要手动处理,但是HTTP1.1之后,Connection:keep-alive已经被列入了规范,现在基本都是默认就是长连接,前提是同一个源,向不同源发送请求要重新建立通道

第七步:页面渲染

HTTP1.0和HTTP1.1的一些区别

  • 缀存处理,在HTTP1.0中主要使用header里的If-Modified-SinceExpires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如EntitytagIf-Unmodified-SinceIf-MatchIf-None-Match等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化及网络连接的使用,HTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了 range头域,它允许只请求资源的某个部分,即返回码是206( Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  • 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  • Host头处理,在HTP1.0中认为每台服务器都绑定一个唯一的地址,因此,请求消息中的URL并没有传递主机名( hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机( Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)
  • 长连接,HTTP1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-ave,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

HTTP2和HTTP1.X相比的新特性

  • 新的二进制格式(BinaryFormat),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP20的协议解析决定采用二进制格式,实现方便且健壮。
  • 多路复用( MultiPlexing),即连接共享,即每一个 request都是是用作连接共享机制的。一个 request.对应一个id,这样一个连接上可以有多个 request.,每个连接的 Request可以随机的混杂在一起,接收方可以根据 request的id将 reques再归属到各自不同的服务端请求里面
  • header压缩,如上文中所言,对前面提到过HTTP1.x的 header带有大量信息,而且每次都要重复发送,HTTP2.0使用 encoder来减少需要传输的 header大小,通讯双方各自 cache一份 header fields表,既避免了重复 header的传输,又减小了需要传输的大小。
  • 服务端推送( server push),例如我的网页有一个sytle.css,在客户端收到 sytle.css数据的同时,服务端会将 sytle.js的文件推送给客户端,当客户端再次尝试获取 sytle.js时就可以直接从缓存中获取到,不用再发请求了。

HTTP2.0的多路复用和HTTP1.X中的长连接复用有什么区别?

  • HTTP/1.*:一次请求响应,建立一个连接,用完关闭;每一个请求都要建立一个连接。
  • HTTP/1.1:若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞。
  • HTTP/2多个请求可同时在一个连接上并行执行,某个请求任务耗时严重,不会影响到其它连接的正常执行。

性能优化总结

利用缓存

  • 对于静态资源文件实现强缓存和协商缓存(扩展:文件有更新,如何保证及时刷新?)
  • 对于不经常更新的接口数据采用本地存储做数据缓存(扩展cookie/localStorge/vuex|redux区别)

DNS优化

  • 分服务器部署,增加HTTP并发性(导致DNS解析变慢)
  • DNS Perfetch

TCP 的三次握手,四次挥手

  • Connection:keep-alive

数据传输

  • 减少数据传输大小
    • 内容或者数据压缩(webpack等)
    • 服务器端一定要开启GZIP压缩(一般能压缩60%左右)
    • 大批量数据分批次请求(例如:下拉刷新或者分页,保证首次加载请求数据少)
  • 减少HTTP请求次数

CDN服务器 “地域分布式”

采用HTTP2.0

网络优化师前端性能优化中的重点内容,因为大部分的消耗搜发生在网络层,尤其是第一次页面加载。如何减少等待时间很重要"较少白屏的效果和时间"。Loading人性化体验、骨架屏:客户端骨屏+服务器骨架屏、图片延迟加载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用Java上传图片到服务器并返回下载URL的过程中,可以按照以下步骤进行操作: 1. 首先,需要使用Java的文件操作相关类和网络编程相关类,例如可以使用java.io.File类和java.net.HttpURLConnection类。 2. 从本地计算机上选择要上传的图片文件,并利用File类创建一个File对象,指向该文件。 3. 创建一个URL对象,指向服务器的URL地址,如http://www.example.com/upload.php。 4. 打开一个HttpURLConnection连接,使用该连接与服务器进行通信。 5. 设置连接的请求方法为POST,以向服务器发送数据。 6. 设置连接的参数和请求头,如设置请求头的Content-Type为multipart/form-data,并设置其他相关的请求头信息。 7. 创建一个DataOutputStream对象,通过该对象将文件数据写入连接的输出流中,实现文件的上传。 8. 通过连接的输入流获取服务器的响应数据,这里可以通过读取InputStream流将返回的数据进行读取。 9. 解析服务器返回的响应数据,可以是一个包含了上传文件的下载URL的字符串。 10. 关闭连接,释放资源。 可以使用Apache HttpClient、OkHttp等第三方库来简化网络请求操作,这些库提供了更方便的方法和接口,可以简化代码的编写和优化性能。 需要注意的是,服务器端也需要有相应的代码来接收上传的图片文件,保存到指定位置,并返回下载URL给客户端。具体的实现方式取决于服务器端的开发环境和框架。 以上是一种较为常见的实现方式,具体的实现细节和代码结构可能会有所不同,根据实际需求进行相应的调整。 ### 回答2: 在Java中实现图片上传至服务器并返回下载URL的过程如下: 1. 首先,你需要使用Java的文件上传技术将本地图片上传到服务器。可以使用Apache的HttpClient库发送HTTP POST请求来实现文件上传。具体步骤如下: - 创建一个`HttpClient`对象。 - 创建一个`HttpPost`对象,并设置请求的URL。 - 创建一个`MultipartEntityBuilder`对象,用于构建包含文件和其他参数的请求实体。 - 使用`addBinaryBody`方法将要上传的图片添加到请求实体中,同时可以设置图片的MIME类型和文件名。 - 可选地,可以使用`addTextBody`方法添加其他参数。 - 将请求实体设置给`HttpPost`对象。 - 发送`HttpPost`请求,并获取响应。 2. 在服务器端,你需要根据接收到的文件,将其保存到指定位置。你可以使用Java的Io技术来实现文件的保存。 3. 保存文件后,你需要为该文件生成一个可访问的下载URL。你可以使用服务器的URL和保存的文件路径拼接而成的URL作为下载URL。 注意事项: - 上传图片时,需要确保服务器端有足够的存储空间,并且对上传文件的大小进行限制,以防止过大的文件拖慢服务器性能。 - 在上传图片之前,可以在客户端对图片的大小和类型进行校验,以提前减少无效的上传操作。 - 保存文件之后,为了能够让其他人可以访问到该文件,可能需要对保存的文件进行权限设置。 - 在生成下载URL时,建议使用绝对路径而不是相对路径,以避免由于路径变动导致无法正常访问文件的问题。 以上就是用Java实现图片上传至服务器并返回下载URL的基本步骤。具体的代码实现可以根据具体的开发框架和需求进行调整。 ### 回答3: 要实现在Java中上传图片至服务器并返回下载URL的功能,可以使用如下的步骤: 1. 创建一个Java后台服务器,用于接收客户端上传的图片文件。 2. 在前端(例如HTML页面)中,使用表单来上传图片文件。 3. 在Java后台服务器上,使用Java的Servlet或Spring MVC等框架来处理文件上传请求。 4. 在Java后台服务器上,可以使用Apache Commons FileUpload或其他相应的库来处理文件上传。 5. 在Java后台服务器中,将接收到的图片文件保存到指定的服务器文件夹中。 6. 可以为每个上传的图片文件生成一个唯一的文件名,以避免重名的冲突。 7. 将保存在服务器文件夹中的图片文件的路径和文件名返回给客户端。 8. 客户端可以使用返回的路径和文件名来拼接成完整的下载URL。 9. 客户端可以通过浏览器或其他HTTP请求方式来下载这个图片。 10. 当需要下载图片时,客户端可以使用下载URL来获取服务器上的图片。 总结,要实现在Java中上传图片至服务器并返回下载URL,需要在前后端之间进行数据的传递,并在服务器端进行相应的文件处理,最后返回文件的路径和文件名给客户端。这样客户端可以通过拼接路径和文件名来获取服务器上的图片。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值