京东前端开发实习生 一面

前言

就说我这次的面试体验来说,萝莉来形容我还是太强壮了,算了不说了。

下面是面筋一览,下面必须尝试手撕找回颜面

  • 1.自我介绍
  • 2.ai使用率
  • 3.日常如何使用 ai
  • 4.项目中打断ai语音输出时如何区分人声和噪声
  • 5.架构选型如何决定
  • 6.实习经历(主要做什么、遇到的难题是什么)
  • 7.如何优化h5页面的性能 ★★★
  • 8.强缓存和协商缓存的区别 ★★★
  • 9.如果有大量的 dom 操作和 dom动画一起执行会发生什么-faber架构 ★★★
  • 10.http1.0和http2.0的区别 ★★★
  • 11.https TLS加密的过程 ★★★

一、自我介绍(可跳过)

这里就不暴露个人信息了,核心是围绕自己的亮点和优势来介绍

二、ai使用率(可跳过)

面试官的心思谁能琢磨透呢?想让我们多用AI吗?还是相反的?

既然前面都说了用了那么多AI技术了,那肯定是80%以上啊(事实也确实如此,甚至更高)

三、如何使用 ai(可跳过)

AI是万能的,但是我们也不能一点事不干,不然会给面试官留下只会AI的思想侏儒。

现在随着AI Coding的兴起,更可贵的是产品思维,AI的工作应该是一种提效的工具而不是一种平替。AI Coding时代下需要的是一个有大局观的知识面广的指挥者,,所以要打出你和AI的组合技。下面是一种很好的回答,日常工作也建议这样做。

我有一个很好的idea,我认为这个idea很有前景,有商业价值,AI可以帮我调研完善这个萌芽状态下的idea,技术的选型和项目的基础架构也是我来完成的,AI负责完成具体的功能模块的代码实现,因为AI对小的细节方面的把控是很优秀的,之后使用AI做代码的review。

四、项目中如何实现的AI对话语音打断机制(可跳过)

项目使用的是VAD打断机制,目的是把一个死板的 WebSocket 管道,变成一个灵活的、可交互的"人"。

用的 VAD 算法其实非常经典且基础,叫 基于能量的检测。

  • RMS (Root Mean Square,均方根):用来衡量一段声音的"响度"。
  • 想象一个波形图,上下跳动。如果波形平平的(比如 0.001),说明没声音;如果波形剧烈跳动(比如 0.5),说明有声音。
  • 算法就是:把这一帧里所有的采样点(比如 4096 个点)平方 -> 加起来 -> 除以总数 -> 开根号。这就是这段音频的"平均能量"。

逻辑流程:

  1. 算响度:每来一帧音频(约 0.1 秒),就算一次 RMS。
  1. 比阈值:设一个红线(SILENCE_THRESHOLD = 0.02)。
  • RMS < 0.02:认为是静音/噪音。
  • RMS > 0.02:认为是人声。
  1. 防抖动:
  • 问题:如果我就拍了一下桌子(啪!),RMS 瞬间飙高,但这不算说话,不能打断 AI。
  • 解决:也就是你代码里的 SPEECH_FRAMES_THRESHOLD = 5。必须连续 5 帧(约 0.5 秒)都超过红线,系统才认定"这人真在说话",然后触发打断。

但是RMS 的 VAD 最大的短板就是无法区分'人声'和'背景噪音'。

在目前的 Demo 环境(安静室内),这个方案效果很好且极度轻量(计算量几乎为 0)。如果要在生产环境(如咖啡厅)解决这个问题,我有两套成熟的升级方案:

  1. 前端方案:引入 WebRTC VAD 或 rnnoise(基于 RNN 的降噪库) ,它们能提取音频特征,识别是否是'人声频谱',而不仅仅看响度。

  2. 后端方案(更推荐):阿里云 Qwen-Omni 协议本身支持 server_vad 。我可以把判断逻辑交给云端模型,因为大模型对语音的理解能力远强于本地算法。我只需把所有音频流上去 ,如果服务端下发 input_audio_buffer.speech_started 事件,我再执行打断。这能极大降低误触率。

五、架构选型如何决定(根据个人的技术栈来选择的)

因为我的方向是大前端下的全栈开发,所以选型我会从下面的方向考虑------

1.是否需要SEO(React和Next.js)

React 与 Next.js 的选择核心看项目需求:

无 SEO 需求、侧重纯客户端交互的场景(如浏览器插件、内部 AI 工具),选React,搭配 Vite 打包体积小,聚焦前端流畅体验;

需 SEO、首屏优化或快速搭建 AI 接口中间层的场景(如 AI 内容平台、对外工具),选Next.js,其 SSR/SSG 能力和 API Routes 能降低全栈开发成本。二者并非替代关系,Next.js 是基于 React 的增强框架。

2.移动端应用还是PC端应用(UI架构选择)

  • PC 端(如 AI 管理后台、代码助手) :优先选 Ant Design Pro/Element Plus,这类组件库适配大屏,自带复杂表格、权限菜单、多窗口布局,契合 AI 平台参数配置、数据可视化需求;ToC 创新工具可选 Tailwind+Radix UI,灵活定制个性化交互。
  • 移动端(如 AI 对话 APP、移动端生成工具) :选 Vant/PrimeVue Mobile,组件适配触屏操作,支持响应式布局;跨端场景用 Ionic 或 React Native Web,一套代码覆盖移动端与 Web;轻量化 H5 选 UnoCSS,减少加载体积。

3.后端框架选择

作为偏前端的全栈开发者,我会优先选择 "Next.js API Routes + 云服务 + 轻量级后端" 的组合,减少后端维护成本。

对于中大型的项目,我会使用使用更轻量的Egg.js是由阿里巴巴开源的基于koa,小型项目会选择Express

中大型项目选 Egg.js(阿里开源、基于 Koa),因其内置约定式目录规范、分层架构和企业级插件体系(如多环境配置、日志),能规避代码混乱,适配复杂逻辑(如 AI 接口分层、多模型调用),长期维护成本低;

小型项目选Express,它极简无约束,几行代码就能搭建接口,无需遵循固定规范,快速落地轻量需求(如单接口 AI 工具),避免 Egg.js 的配置冗余,提升迭代效率。

4.数据库选择(Mysql、MongoDB、supabase)

结构化数据 + 强事务需求(如 AI 平台的用户计费、权限),中大型项目选 MySQL,依托其 ACID 特性和关联查询优势;非结构化 / 半结构化数据(如 AI 对话历史、模型参数),选 MongoDB,无 Schema 约束适配灵活扩展。

小型项目优先 Supabase,作为 PostgreSQL-based 的 BaaS 平台,零代码实现认证、实时同步,快速落地核心功能;若仅需轻量存储非结构化数据,也可选 MongoDB。

六、实习经历(主要做什么、遇到的难题是什么)

实习经历要突出自己的工作特点并使用工作经历来佐证,而且要细讲一个在工作中主要负责的项目,其它的几句话带过

七、如何优化h5页面的性能 ★★★

这个问题是整个面试过程中最核心的问题,涉及到了前端开发的各个方面,需要慎重回答,我的答案也肯定不完全,欢迎评论区补充

我们可以从七个维度展开来讲------加载阶段优化渲染阶段优化运行阶段优化网络交互优化适配与兼容优化性能监控与持续迭代react优化

(1)加载阶段优化:资源最小化与传输智能化

1. 资源压缩与优化
  • 代码级压缩

    • JS/CSS压缩 :使用 TerserCSSNano 进行混淆、删除死代码。★★★
    • Tree Shaking:通过ES6模块静态分析,剔除未使用的导出代码(如仅导入UI库的特定组件)。
    • 现代图片格式优先使用WebP/AVIF ,相比PNG/JPEG可减少30%-70%体积。为兼容性提供 <picture> 标签降级。★★★
    • 图片尺寸适配 :通过 srcsetsizes 属性,根据设备DPR和视口宽度加载最合适的图片。★★★
    • 字体子集化 :使用 fonttools 等工具提取页面实际使用的字符(尤其对于中文字体),生成精简的WOFF2文件。
2. 智能加载策略
  • 关键渲染路径优化

    • 内联关键CSS :将首屏渲染(Above The Fold)所必需的CSS直接内嵌在HTML <style> 标签中,消除请求阻塞。★★★
    • 异步/延迟非关键JS :使用 async(独立模块)或 defer(保持顺序)属性加载非阻塞脚本。★★★
  • 资源提示

    • preload:强制高优先级加载当前页面的核心资源(如关键字体、首屏英雄图)。
    • preconnect / dns-prefetch:提前与第三方域名建立TCP连接或进行DNS解析。
    • prefetch低优先级预获取下一个导航可能需要的资源。
  • 按需加载/懒加载

    • 路由懒加载 :使用 import() 动态导入路由组件。★★★
    • 组件懒加载:非首屏交互组件(如AI工具的复杂参数面板)在需要时加载。★★★
    • 图片/iframe懒加载 :使用原生 loading="lazy"IntersectionObserver API实现。★★★
3. 缓存策略★★★
  • 强缓存 :为带Hash指纹的静态资源设置 Cache-Control: max-age=31536000(一年)。★★★
  • 协商缓存 :对可能变化的资源使用 ETag/Last-Modified。★★★
  • Service Worker缓存:实现更精细的离线缓存、网络降级和资源预缓存策略。
  • 本地存储 :将不敏感的AI模型配置、用户偏好存入 localStorage,减少接口请求。★★★
4. 构建与传输优化
  • 代码分割:基于路由、组件或动态导入,将代码拆分成多个按需加载的Chunk。
  • 启用HTTP/2/HTTP3:利用多路复用、头部压缩等特性提升传输效率。★★★
  • 开启Brotli/Gzip压缩:在服务器端对文本资源进行高效压缩。

(2)渲染阶段优化:绘制高效与避免抖动

目标:加速首屏绘制,最小化重排与重绘

1. 避免布局抖动
  • 读写分离 :避免在循环中连续读取(如 offsetHeight)然后写入样式,应批量读取后统一写入。
  • 使用 DocumentFragment:进行离线DOM操作,完成后一次性插入文档。
  • 避免强制同步布局 :在 requestAnimationFrame 回调中处理样式修改,与浏览器刷新率同步。
2. CSS优化
  • 简化选择器:避免过于复杂的选择器链,减少样式计算开销。
  • 优化动画属性仅使用 transformopacity 制作动画,它们只触发合成层(Compositing) 更新,由GPU处理,性能极高。避免使用 left, top, margin 等触发布局和绘制的属性。★★★
  • 提升为合成层 :对复杂动画元素谨慎使用 will-change: transformtranslateZ(0),提示浏览器提前优化。
  • 使用Flexbox/Grid布局:相比传统浮动和定位布局,性能更优且更不易引发布局问题。★★★
3. 首屏体验优化★★★
  • 服务端渲染/静态生成:对于内容型AI页面,使用Next.js/Nuxt.js等框架进行SSR/SSG,直出HTML,消除白屏。★★★
  • 骨架屏:在数据加载前,展示与最终页面结构相似的灰色占位图,极大提升感知速度。★★★

(3)运行阶段优化:交互流畅与内存健康

目标:确保主线程响应迅速,防止内存泄漏

1. JavaScript执行优化
  • 拆分长任务 :任何连续执行超过 50ms 的任务都可能阻塞交互。使用 setTimeoutrequestIdleCallbackWeb Worker 进行拆分。★★★

    • Web Worker应用 :将AI项目中的大文本处理、模型推理(TensorFlow.js)、复杂计算移至Worker线程。★★★
  • 防抖与节流 :对 resizescrollinputmousemove 等高频率事件进行控制。★★★

  • 事件委托:利用事件冒泡,在父节点统一处理子元素事件,减少监听器数量。★★★

2. 高效数据渲染
  • 虚拟列表 :对于AI对话记录、生成结果等长列表,只渲染可视区域及其附近的DOM元素 (使用 react-windowvue-virtual-scroller 等)。★★★

  • Canvas优化:对于AI绘图或数据可视化:★★★

    • 使用分层Canvas,仅重绘变化的层。
    • 限制画布分辨率,适配显示尺寸即可。
    • 利用 OffscreenCanvas 在Worker中绘图。
3. 内存管理
  • 及时清理:移除不再需要的事件监听器、定时器、WebSocket连接。
  • 避免意外全局变量
  • 解除引用 :对于不再需要的大型对象(如AI生成的高清图片数据URL),手动设置为 null
  • 使用弱引用 :对于缓存场景,考虑使用 WeakMapWeakSet。★★★

(4)网络交互优化:请求高效与弱网友好

目标:减少请求数量、压缩传输数据、提升连接效率

1. 请求优化
  • 合并请求:将同类型小请求合并(如多个配置查询)。
  • 请求优先级管理:核心接口优先,非关键请求(如日志、统计)延迟或空闲时发送。
  • 取消无用请求 :在组件卸载或用户跳转时,取消未完成的 fetch / axios 请求。
  • 接口缓存:对非实时AI数据(如模型列表、公共配置)进行合理的本地或Service Worker缓存。
2. 数据传输优化
  • 使用现代数据格式 :考虑使用 Protocol Buffers (PB)MessagePack 替代JSON,可大幅减少AI模型输入输出等大数据的传输体积。
  • 开启压缩 :确保API响应头包含 Content-Encoding: brgzip。★★★
  • 流式响应 :对于AI对话、文本生成等场景,使用 SSEWebSocket 进行流式传输,实现"打字机"效果,大幅降低可感知延迟。★★★
3. 网络环境适配
  • 弱网检测与降级 :通过 navigator.connection.effectiveType 检测网络类型,弱网下自动降低图片质量、关闭预览动画、使用更简洁的UI。
  • CDN与边缘计算:静态资源部署CDN。将部分AI预处理逻辑(如图片压缩、格式转换)通过边缘函数(如Cloudflare Workers)就近处理。

(5)适配与兼容优化:兼顾广泛与高性能

目标:在不同设备与浏览器上提供尽可能一致的性能体验

1. 设备性能分级
  • 硬件检测 :通过 navigator.hardwareConcurrency(CPU核心数)和 navigator.deviceMemory(内存大小)粗略判断设备能力。
  • 动态调整策略:高性能设备启用复杂动画和高清资源;低性能设备则降级为简单动画和基础效果。
2. 浏览器兼容与降级
  • 渐进增强:优先为现代浏览器提供最佳体验(如使用WebGL加速AI推理),同时为旧浏览器提供基础可用的功能。★★★

  • 按需Polyfill :通过 @babel/preset-envuseBuiltIns: 'usage' 仅引入目标浏览器所需的polyfill。

  • 移动端专项:★★★

    • 设置 <meta name="viewport" content="width=device-width"> 消除300ms点击延迟。
    • 为可滚动区域添加 -webkit-overflow-scrolling: touch 以启用平滑滚动。
    • 使用 touch-action: manipulation 禁用双击缩放等默认行为。

(6)性能监控与持续迭代

目标:建立量化指标,驱动持续优化

1. 性能指标采集
  • 核心Web指标 :使用 web-vitals 库轻松测量LCP、FID/INP、CLS。
  • 自定义业务指标:如"AI图片生成完成时间"、"首条对话响应时间"。
  • 长任务监控 :使用 PerformanceObserver 监控超过50ms的任务。
  • 内存监控 :通过 performance.memory(Chrome)监控JS堆大小。
2. 工具与流程
  • 实验室测试 :在CI/CD流程中集成 Lighthouse CI,设定性能预算,不合格则阻断发布。
  • 真实用户监控 :接入 SentryFrontJS 等RUM平台,收集真实环境下的性能数据。
  • 可视化分析 :使用 webpack-bundle-analyzer 定期分析产物构成,警惕体积膨胀。

(7)React框架专项优化:从模式到细节的性能实践

React应用的核心性能问题通常源于 不必要的重新渲染 。优化目标是:在正确的时间、只渲染必要的组件

1. 用 useCallback + useMemo 避免无意义计算与重渲染

这两个 Hook 是解决函数 / 计算结果重复生成导致子组件重渲染的关键,要区分清楚各自的使用场景,避免滥用。

  • useCallback:缓存函数引用

    • 原理:缓存函数的引用地址,只有当依赖项变化时,才会生成新的函数。
    • 适用场景:父组件传递函数给子组件时,若子组件用 React.memo 做了浅比较优化,必须用 useCallback 包裹传递的函数,否则每次父组件渲染都会生成新函数,导致子组件无效重渲染。
    • 项目案例:在 AI 可视化项目中,我给图表组件传递的 onDataChange 回调,用 useCallback 包裹后,避免了图表组件因函数引用变化而重复渲染,提升了大数据渲染时的流畅度。
    • 避坑点:不要无脑包裹所有函数,依赖项要写全,否则会导致闭包陷阱(比如引用旧的 state)。
  • useMemo:缓存计算结果

    • 原理:缓存复杂计算的结果,只有依赖项变化时才会重新计算。
    • 适用场景:组件内有大量计算逻辑(比如 AI 模型输出数据的格式化、长列表的筛选排序),避免每次渲染都重复计算。
    • 项目案例:在智能表单项目中,我用 useMemo 缓存了表单校验规则的计算结果(依赖于表单配置),减少了表单组件每次输入时的计算开销,输入响应速度提升约 30%。
    • 避坑点:简单计算没必要用 useMemo(比如数字加减),其本身有缓存开销,反而可能适得其反。

2. 合理使用受控组件 vs 非受控组件,平衡性能与开发效率

这两种组件模式的选择,直接影响表单类组件的性能和用户体验,要结合场景取舍:

  • 受控组件 :表单数据由 React state 控制,优点是实时校验、数据联动方便;缺点是高频输入场景下(比如搜索框实时联想) ,每次输入都会触发 state 更新和组件重渲染,可能有性能损耗。

    • 优化技巧:高频输入场景可加防抖处理,比如搜索框输入时,延迟 300ms 再更新 state,减少重渲染次数。
  • 非受控组件 :表单数据由 DOM 自身维护,通过 ref 获取值,优点是性能更高(减少 state 驱动的重渲染);缺点是数据联动、实时校验不如受控组件灵活。

    • 适用场景:文件上传、简单输入框(无需实时校验)、高频输入的搜索框等场景。
    • 项目案例:在 AI 对话系统的输入框中,我采用非受控组件 + 防抖 ref 取值的方案,既保证了用户输入的流畅性,又避免了实时 state 更新带来的性能开销。

3. 长列表优化:解决大数据渲染的性能瓶颈

长列表(比如 1000+ 条数据)直接渲染会导致 DOM 节点过多,引发首屏加载慢、滚动卡顿,这是前端性能优化的高频考点,尤其在 AI 数据可视化场景中很常见。

  • 核心方案:虚拟列表(Virtual List)

    • 原理:只渲染当前视口内可见的列表项,滚动时动态替换可视区域的内容,复用 DOM 节点,减少 DOM 数量。

    • 实现方式:

      1. 手写简易版:通过计算视口高度、列表项高度,确定可视区域的起始 / 结束索引,结合 overflow: auto 实现。
      2. 成熟库:比如 react-window/react-virtualized,适合复杂场景(比如动态高度列表、网格布局)。
  • 补充优化:

    • 列表项用 React.memo 包裹,避免单个项的无效重渲染;
    • 数据分页加载 / 懒加载,结合后端接口实现滚动加载更多,减少首屏数据量。

八、强缓存和协商缓存的区别 ★★★

强缓存和协商缓存都是浏览器的缓存技术,目的是为了减少对服务器的资源请求,从浏览器本地拿数据,减少服务器压力,提升访问速度,但是强缓存和协商缓存又有不同。

强缓存

强缓存通过请求头中设置的Expires和Cache-Control来控制,其中Expires是http1.0时的协商缓存请求头,Cache-Control是http1.1推出的请求头,现代浏览器大部分情况下使用Cache-Control来控制强缓存。

Expires是通过设置绝对时间来控制强缓存的时间的,如Expires: Wed, 21 Oct 2025 07:28:00 GMT。这就导致用户可以通过修改系统时间来导致强缓存失效,所以Cache-Control出现之后Expires就基本不使用了。

Cache-Control的主要属性值包括:

  • private:响应仅能被客户端缓存,不能被代理服务器缓存
  • public:响应可以被客户端和代理服务器缓存
  • max-age:设置缓存的最大有效期(秒)
  • no-cache每次使用缓存前必须向服务器验证(启用协商缓存)
  • no-store:禁止任何形式的缓存
  • must-revalidate:缓存过期后必须向服务器验证
  • immutable:资源在有效期内不会改变(适合版本化资源)

当要请求一个资源时,如果启用了强缓存,第一次缓存会请求服务器然后会将资源缓存到本地内存或磁盘,如果缓存没有过期的情况下再次请求就会直接从内存或磁盘拿数据,不会请求服务器,大幅减少了服务器压力,也提高了前端的响应速度。

那么什么时候存到内存,什么时候存到磁盘呢?一般来说体积小、多次复用、过期时间短的会存在内存,反之存到磁盘,这时由浏览器决定的,是一个黑盒的过程,但是我们可以通过某种手段去影响浏览器的判断,比如将过期时间设置的短一点,就越有可能存到内存中。

我们这里也可以总结一下强缓存的优缺点。优点是设置了过期时间之后不会请求服务器,减少了服务器的压力和宽带开销;缺点是过期时间之前缓存的数据是不会更新的,如果服务器的数据更新了,但是本地缓存还没有过期,就会导致数据不同步的问题,所以,一般来讲,强缓存要存储不常改变的资源,如vue.js

协商缓存

协商缓存是通过设置请求头中的Last-Modified(If-Modified-Since)、ETag (If-None-Match)来控制的。其中请求头Last-Modified(If-Modified-Since)是http1.0中设置的请求头,ETag (If-None-Match)是http1.1推出的新的协商缓存请求头,现代浏览器大部分情况下使用ETag (If-None-Match)来控制协商缓存。

Last-Modified(If-Modified-Since)是通过判断文件的修改时间来确定是否使用缓存资源的,不论是否真正的修改内容。这就导致某些情况下浪费宽带

ETag (If-None-Match)是通过判断文件的内容是否修改来确定是否使用缓存的,相比于Last-Modified(If-Modified-Since)更加精细实用。具体的过程是,当启用Etag协商缓存时,第一次请求并不会携带请求验证,服务器在返回资源时会在响应头中返回一个Etag,这个值是服务器根据资源内容生成的唯一标识符,当下次请求时就会在请求头带入If-None-Match,值就是第一次请求时返回的Etag值。请求过去的时候服务器会比较If-None-Match和新的Etag值是否一样,如果一样就返回304 Not Modified不返回资源,意思是通知前端资源没有变可以从浏览器拿取缓存,如果值不一样,说明资源改变,这时就返回200状态码并返回新的资源

我们可以看到协商缓存的优劣。优势是可以实时的更新最新数据不害怕资源过期,但是比起强缓存,协商缓存多了网络请求的往返,这样会导致网络延迟的发生。所以协商缓存适合动态内容、API响应、可能频繁更新的资源(如未版本化的HTML)

九、如果有大量的 dom 操作和 dom动画一起执行会发生什么-faber架构 ★★★

我认为这一题就是考察我们对react虚拟dom和faber架构调度机制的理解,这里推荐一篇文章 浅谈React中虚拟DOM、diff算法、fiber架构的关系(面试可用)- 掘金

十、http1.0和http2.0的区别 ★★★

首先明确导致延迟的罪魁祸首是什么,无疑是带宽和队头阻塞。

带宽影响了单位时间最大的数据通过量,队头阻塞则影响了数据的传输效率

虽然近年来网络带宽增长非常快,然而我们却并没有看到网络延迟有相应程度的降低。网络延迟问题主要由于队头阻塞,导致带宽无法被充分利用

由http1.0到http2.0的过程一大半就是解决队头阻塞的过程。

http1.0

首先我们来看http1.0,http1.0只允许短链接,而且每个短链接只允许单个请求,也就是每个http请求都要进行一次TCP连接,连接之后TCP连接会断开,下次http请求还要重新建立一个TCP连接,每个请求都有TCP三次握手(1.5RTT)和四次挥手开销,导致服务器压力大,队头阻塞网络延迟严重。

此外,http1.0无主机头,无法实现虚拟主机,浪费IP资源;缓存机制简陋,只有基本的 ExpiresLast-Modified;只有16个状态码;不支持https;不支持响应体压缩;不支持文件的分段上传,浪费带宽

http1.1

之后是http1.1的时代,相比于http1.0,http1.1有较大的进步,也有一些遗留问题没有解决。

最核心的进步是http1.1支持长连接(Connection: keep-alive;Keep-Alive: timeout=5, max=100 ),减少了多次建立TCP连接的开销,一次TCP连接可以进行多个http请求,而且支持管道化(管道化是一次失败的尝试,可以忽略,之后会讲)

此外http1.1支持了虚拟主机,一个ip可以托管多个网站;增强了缓存机制,新增了头部Cache-Control和Etag,这也是现代最常用的强缓存和协商缓存头部;支持资源的分段上传,节省了宽带的兄消耗;新增了协商缓存;新增了patch方法;

但是还有遗留问题没有解决,比如管道化的并行尝试,因为http1.1是基于文本协议传输,所以传输时需要以http请求为单位,就会导致多个http请求出现互相等待的问题,而且管道化要求请求的顺序返回,如果第一个请求很慢,但是第二个第三个很快,就会出现第二个第三个等待的现象,并不能真正实现并行请求;所以管道化在实际开发中并不会被使用,尽管http1.1允许了长连接,但是还是一个一个请求处理的,而一个ip只允许同时6个tcp连接,还是会出现队头阻塞的问题;而且http1.1不支持请求头的压缩,导致很多情况下队头的体积要比响应题的体积还要大;服务端没有主动推送的功能

http2.0

http2.0向下兼容了http1.X,但和http1.x不同的是,http2.0不是基于文本数据传输的,而是基于二进制数据流进行传输,这就很大程度上解决

最核心的进步是HTTP/2.0的二进制分帧机制。它将所有传输内容拆分为二进制帧(Frame),每个帧标记流ID。不同请求/响应通过不同流并行传输,从应用层解决了HTTP队头阻塞问题------即使某条流的帧丢失,也仅阻塞该流而不影响其他流传输。

在HTTP/2.0中,单个TCP连接可承载任意数量的双向流(Stream),每个流独立传输请求/响应,无需新建连接。这实现了连接的完全复用,大幅提升了传输效率。需要注意的是,HTTP/2.0仅解决了应用层队头阻塞,TCP层仍存在队头阻塞问题,这正是HTTP/3.0改用QUIC协议要解决的。

此外,http2.0实行了头部压缩,大幅减少头部传输体积,通过 HPACK 算法实现头部压缩:

  • 静态字典:预定义常用头部字段(如 Host、Accept-Encoding),用整数索引替代完整字符串;
  • 动态字典:记录当前连接中重复出现的头部字段(如自定义的 Token 头),后续传输仅需索引;
  • 哈夫曼编码:对非字典字段进一步压缩。

http2.0允许服务器推送主动推送关键资源,首屏加载时,服务器可提前推送 AI 工具的核心 JS(如对话逻辑、模型接口封装)和首屏图片,缩短首屏渲染时间

十一、https TLS加密的过程 ★★★

http1.x的文本传输也好,http2.0的二进制分帧也好,都是明文传输的,这样就会导致内容可能会被窃听身份可能被伪造报文可能被篡改

https就极大的提高了http的安全性,区别是在http的三次握手之后多出了一个TLS握手,我们现在要讲解的就是TLS握手的过程。下面我们先了解一些前置的知识。

两种加密方式------对称加密和非对称加密

对称加密

对称加密,客户端和服务器使用同一个密钥(加密算法)去加密数据,这个密钥可以加密数据也可以解密数据。但是如果有第三方知道了这个密钥,就可以解密数据,安全性不高。而这个密钥需要在客户端和服务器端传输,就加大了密钥泄露的风险

非对称加密

非对称加密使用公钥和私钥进行加密和解密,通常情况下公钥只用来加密,没有解密功能,而私钥可以解密这个公钥加密的数据。通常情况下,服务器会把公钥传给客户端,客户端对数据使用公钥进行加密传给服务端,服务端使用私钥解密数据,这时如果有人截获了客户端发给服务器的数据,他也解密不了,因为私钥在服务器上,而且从头到尾私钥都没有在网络上传输,不会被截获,安全性就大大提升。

TLS1.2的加密

其实对称加密和非对称加密各有优劣,对称加密安全性不高,但是传输效率高,没有冗余操作;非对称加密安全性高,但是效率低,那么有没有一种方法可以取二者精华,避二者糟粕呢?有的。

首先是对称加密的不安全性是在哪?是因为密钥容易泄露,如果这个密钥不会泄露的话,就可以解决对称加密的不安全的问题。而非对称加密是安全的,可以使用非对称加密去生成一个安全的不会被泄露的密钥,然后使用这个密钥去进行非对称加密,这样就可以得到一个安全的、高效的加密方式

上面的加密方式就解决了http的第一个安全性的问题------内容可能会被窃听

SSL证书

SSL 证书 是一种基于公钥基础设施(PKI)的数字证书,由权威的第三方证书颁发机构签发,用于验证服务器身份,并为客户端与服务器之间的通信建立加密链路。后续 SSL 协议升级为更安全的TLS 协议 ,因此 SSL 证书也常被称为 TLS 证书

这个证书用于身份验证,SSL 证书包含以下关键信息,用于身份验证和加密通信:

  1. 服务器域名:证书绑定的域名 / IP,确保客户端访问的是目标服务器;
  2. 公钥:用于加密通信数据或验证数字签名,可公开传输;
  3. 私钥:由服务器持有,用于解密公钥加密的数据或生成数字签名,需严格保密;
  4. 证书颁发机构(CA)信息:签发证书的权威机构,包含 CA 的数字签名;
  5. 证书有效期:证书的生效和过期时间,过期后需重新签发。

SSL证书可防止中间人攻击域名劫持

  • 客户端(如浏览器)访问 HTTPS 网站时,服务器会向客户端出示 SSL 证书;
  • 客户端通过内置的 CA 信任列表,验证证书是否由可信 CA 签发、是否在有效期内、是否绑定当前访问的域名;
  • 若验证通过,确认服务器身份合法;若验证失败(如证书伪造、过期、域名不匹配),浏览器会弹出安全警告,提示用户停止访问。

典型的比如www.bilibili.com和www.bi1iXXXX.com. 这样就可以解决身份可能被伪造的问题

MAC
  • TLS 1.2:通过将明文数据、派生的 MAC 密钥等参数经 HMAC 算法算出 MAC 值并随加密数据一同传输,接收方解密后重新计算 MAC 值比对来判断报文是否被修改。
  • TLS 1.3:借助 AEAD 算法在加密数据时同步生成认证标签,接收方解密过程中自动验证该标签,以此判断报文是否被修改。

这样可以解决http的第三个安全问题------报文可能被篡改

TLS1.2握手过程

下面是具体的TLS1.2的握手过程

  1. 客户端问候(Client Hello) :客户端发送支持的 TLS 版本、加密套件列表、随机数 Client Random,并附带会话 ID(用于会话复用)。
  2. 服务器问候(Server Hello) :服务器从客户端列表中选定 TLS 版本和加密套件,返回随机数 Server Random,并确认会话 ID。
  3. 服务器证书与密钥交换:服务器发送自身 SSL 证书(含公钥);若使用 RSA 等非对称加密套件,直接等待客户端加密密钥;若使用 DH/ECDHE 等密钥协商算法,发送服务器端密钥交换参数。
  4. 服务器问候完成(Server Hello Done) :服务器通知客户端,问候阶段结束。
  5. 客户端密钥交换 :客户端验证服务器证书合法性后,生成预主密钥(Pre-Master Secret) ,用服务器公钥加密后发送给服务器;服务器用私钥解密得到预主密钥。
  6. 密钥派生 :客户端和服务器分别使用 Client RandomServer Random、预主密钥,通过 PRF 算法派生主密钥(Master Secret) ,再由主密钥生成会话密钥(包括加密密钥、MAC 密钥)。
  7. 客户端完成(Client Finished) :客户端用会话密钥加密握手消息摘要,发送 Finished 消息,验证握手过程未被篡改。
  8. 服务器完成(Server Finished) :服务器同理加密握手消息摘要,发送 Finished 消息;双方验证通过后,握手完成,后续用会话密钥加密传输应用数据。

所以整个流程是非对称加密的,握手之后则是对称加密,那么非对称加密的密钥为什么不会泄露呢?整个密钥是有预主密钥+Client Random+Server Random生成的,而且预主密钥并没有在网络上暴露,只是暴露的加密后的预主密钥,这个密钥就算暴露,他人也无法解析,因为私钥在服务器上,所有就形成了安全的对称加密。

TLS1.3握手过程

TLS 1.3 握手的核心目标是 极简交互、1-RTT 时延、强制前向安全 ,主流分为基础 1-RTT 握手 (首次连接)和 0-RTT 快速握手(会话复用)两种模式,以下是详细步骤:

基础 1-RTT 握手(首次连接,单向认证场景)

单向认证是最常见的场景(如浏览器访问 HTTPS 网站),仅服务器需提供证书,流程共 2 轮交互:

  1. 客户端 → 服务器:发送 Client Hello

    • 客户端发送支持的 TLS 1.3 版本、AEAD 加密套件列表(如 AES-GCM)、Client Random 随机数、会话 ID(用于后续复用)。
    • 核心新增 :携带客户端生成的 ECDHE 临时公钥,提前启动密钥协商流程。
    • 可选附带扩展信息(如支持的 0-RTT 功能)。
  2. 服务器 → 客户端:发送 Server Hello + 证书 + Finished

    • 服务器选定加密套件和 Server Random 随机数,返回 服务器 ECDHE 临时公钥,与客户端公钥配对计算共享密钥。
    • 服务器发送 SSL 证书(含长期公钥),供客户端验证服务器身份。
    • 流程简化关键 :无需发送 Server Hello Done,直接用派生的会话密钥加密握手消息摘要,发送 Finished 消息。
  3. 双方密钥派生

    • 客户端验证证书合法后,结合双方 ECDHE 临时公钥计算 共享密钥
    • 双方通过 HKDF 算法,基于 Client RandomServer Random 和共享密钥,直接派生 会话密钥(无主密钥中间层,AEAD 算法统一处理加密和完整性校验)。
  4. 客户端 → 服务器:发送 Finished

    • 客户端用会话密钥加密握手消息摘要,发送 Finished 消息。
    • 双方验证彼此的 Finished 消息通过后,握手完成,后续用会话密钥传输应用数据。

0-RTT 快速握手(会话复用场景)

若客户端曾与服务器建立过连接,会缓存会话票据和密钥参数,二次连接时可实现 零往返时延

  1. 客户端在 Client Hello 中附带缓存的 会话票据 ,同时直接发送 用缓存密钥加密的应用数据
  2. 服务器验证会话票据合法后,无需重新协商密钥,直接返回 Finished 消息和加密的响应数据。
  3. 双方直接进入数据传输阶段,无需额外握手交互。

结语

感觉自己变强壮了。

相关推荐
光影少年5 小时前
react的hooks防抖和节流是怎样做的
前端·javascript·react.js
小毛驴8505 小时前
Vue 路由示例
前端·javascript·vue.js
发现一只大呆瓜5 小时前
AI流式交互:SSE与WebSocket技术选型
前端·javascript·面试
园小异5 小时前
2026年技术面试完全指南:从算法到系统设计的实战突破
算法·面试·职场和发展
m0_719084116 小时前
React笔记张天禹
前端·笔记·react.js
Ziky学习记录6 小时前
从零到实战:React Router 学习与总结
前端·学习·react.js
wuhen_n6 小时前
JavaScript链表与双向链表实现:理解数组与链表的差异
前端·javascript
wuhen_n6 小时前
JavaScript数据结构深度解析:栈、队列与树的实现与应用
前端·javascript
狗哥哥7 小时前
微前端路由设计方案 & 子应用管理保活
前端·架构
前端大卫7 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端