1. 我是皮皮虾首页
  2. 编程开发
  3. 前端
  4. Vue

前端面试题—平安前端面试题

1.mixin混入,以后自身生命周期和混入周期的具体实现,mixin的具体实现

定义:分发vue中可复用的功能,本质是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods、created、computed等等

局部混入 :

定义一个mixin对象,可能是单文件的形式,有data、methods等属性。在组件中可以定义mixins:[]

在组件使用的时候就混合了mixin里面的方法

全局混入:

Vue.mixin({}) 它会影响每一个组件实例,包括第三方组件,常用于插件的编写

注意:当组件与mixin冲突的时候,会优先组件,但如果为生命周期钩子,会合并成一个数组,先执行mixin再执行组件钩子

使用场景:不同的组件使用相同或者相似的代码,这些组件的功能相对独立。eg:modal弹窗和tooltip弹窗

源码分析:

  • 优先递归处理 mixins
  • 先遍历合并parent 中的key,调用mergeField方法进行合并,然后保存在变量options
  • 再遍历 child,合并补上 parent 中没有的key,调用mergeField方法进行合并,保存在变量options
  • 通过 mergeField 函数进行了合并

合并策略:

  • 替换型策略有propsmethodsinjectcomputed,就是将新的同名参数替代旧的参数
  • 合并型策略是data, 通过set方法进行合并和重新赋值
  • 队列型策略有生命周期函数和watch,原理是将函数存入一个数组,然后正序遍历依次执行
  • 叠加型有componentdirectivesfilters,通过原型链进行层层的叠加

2.nexttick的场景和实现原理

定义:在下一次dom更新循环结束之前执行延迟回调。vue在更新dom时是异步执行的,当数据发生变化时,vue将开启一个异步更新队列,视图需要等到队列完成再更新

原因:

优化策略:在一些非常频繁操作的情况下,每次数据更新都要触发视图更新更新的话,性能存在问题

{{num}}
for(let i=0; i<100000; i++){
    num = i
}
如果没有nexttick 则需要更新10w次视图

使用场景:想要在修改数据后立刻更新视图

实现原理:

  1. 把回调函数放入异步操作队列callbacks等待执行
  2. 将执行函数放到微任务或者宏任务中
  3. 事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调

3.webpack的优化策略,常用插件,热更新的实现原理,如何检测到代码变化

webpack打包经历的几个阶段:

1.根据配置找到打包入口文件;2.根据引用解析并生成一个资源依赖模块树;3.递归这个依赖树,通过文件找到对应的loader;4.打包生成chunk 我们就是围绕着这几个阶段去做优化: 1.loader解析比较耗时 (1) 配置rules.include(exclude高优先级),从源头上减少需要解析的文件 (2) 开启多线程加速loader的解析时间:thread-loader,happypack (3) 利用缓存:cache-loader(mtime),bable-loader(内容缓存开启cacheDirectory:true) (4) noparse: 有些模块没有使用commonjs规范语法,就可以不用转化解析 lodash 2.搜索依赖文件耗时 (1) 设置resolve.alia别名配置路径 (2) resolve.extension(‘xxx’)自动填充文件后缀 默认是[‘.js’,’.json’] 3.打包生成chunk耗时 (1)缓存生成的chunk 设置cache:true 也是默认的 (2)分包(使用webpack-bundle-analyzer,打包依赖工具分析文件并拆分) splitChunksPlugin: cachegroups:{ 设置引用次数,优先级,minsize等等} tree-shaking:usedExports、minimize 生产环境默认开启 sideEffects:用于npm包标记是否有副作用 设置false期望没有。为tree-shaking提供更大的优化空间 其他: IgnorePlugin:webpack内置插件 忽略第三方包的指定目录 externals:有时候我们可能会把一些引入资源放在cdn上,不希望webpack进行打包,但是又想用import方式导入 DLLPlugin:拆分bundle,将不频繁更新的库进行编译,当依赖版本发生变化的时候不需要重新编译 变量提升:scope hoisting:配置new ModuleConcatenationPlugin()分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余。因此只有那些被引用了一次的模块才能被合并。

最后呢,我们在开发阶段呢,也有一些优化我们开发体验的点需要注意: 通过webpack-dev-server:用户开发的http server:可以实现自动编译和自动刷新浏览器,即时修改即时生效,在proxy中配置代理

自动刷新会重新打包,导致浏览器页面丢失。这个时候我们使用模块热更新,集成在web-dev-server里面,不是开箱即用的,需要手动处理热更新逻辑 模块热更新开启:1.web-dev-server –hot 2.通过HotModuleReplacementPlugin插件 配置:module.hot.accept({‘js路径’,‘回调函数(保存状态,remove掉之前的,append一个新的)’},{…图片的话直接将新的地址赋值给图片的src属性})

模块热更新的原理: 热更新的核心就是客户端与服务端建立的websocket连接,服务端监听文件变化,编译后再推送给客户端告之其哪些地方改变了,最终客户端发送ajax请求,获取最新资源,使用文件系统替换修改的内容实现局部更新。 具体步骤:

1.webpack-dev-server启动本地服务(webpack,http server(express),websocket) 2.客户端和服务端使用websocket实现长连接 3.webpack监听源文件的变化,变化后执行重新编译,编译完成后通过socket向客户端推送文件编译后生成的hash串 4.客户端收到推送过来的hash会与上一次的对比,一致则走缓存,不一致则重新发起ajax请求向服务端获取数据 5.使用内存文件系统去替换修改的内容实现局部刷新

常用loader:file-loader、souce-map-loader、babel-loader、ts-loader、css-loader、sass-loader、eslint-loader 常用插件:ignore-plugin、clean-webpack-plugin、html-webpack-plugin、copy-webpack-plugin、hot-module-replacememt-plugin、uglifyjs-webpack-plugin、imagemin-webpack-plugin

4.项目优化方式

vue项目的优化: 1.使用路由懒加载 2.使用keep-alive进行缓存 3.v-for跟v-if不一块使用 4.子组件拆分成更细粒度的,给一些无害组件(没有自己状态,只负责展示展示数据)设置functional,这种情况下可以简化组件的打包体积 5.图片懒加载 我们可以使用lazyload库去实现。原生方法的话都是通过设置一个data-set存储真实的img地址,初始化的时候加载一个占位图或者缩略图,然后根据判断图片是否在可视化范围之内来判断是否加载图片:滚动窗口遍历(节流),new InterceptionObserver(兼容) 6.在组件销毁的时候销毁一些自定义事件,比如监听器。vue组件自动销毁的仅限于组件本身的事件 7.第三方插件按需引入。打包的时候仅会打包引入的部分 8.长列表优化 纯粹数据变化,不用响应式(Object.freeze() or configuration:false;大数据长列表,可以采用虚拟滚动,只渲染少部分内容,用户触发滚动再加载 9.变量的本地化。computed计算属性使用频繁的情况下,单独用变量存储起来再使用 10.服务端渲染ssr 首屏渲染 seo

5.vue项目检测到对象和数组的变化,object.defineProperty和proxy的区别

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

主要是通过getter和setter来实现响应式。修改数据的时候会触发setter,在setter中进行更新操作,如果数据存在多个key的情况下需要遍历,存在嵌套的情况下还需要递归。存在一些问题:

对对象进行删除或者添加属性的操作无法监测到,数组监听也不太凑效。vue2中其实也可以做到遍历监听,但是数据层级深会造成性能问题,所以添加来set、delete这些API去更新。兼容到IE9

proxy的监听是对象层级的,在js语法层面进行支持。可以直接劫持整个对象并返回一个新对象。同时设置了13中拦截方法:has,deleteProperty,ownkeys等等。它不兼容IE,也没有polyfill

trap函数,Reflect

6.Vue 与 其他前端框架 的区别

vue和jquery:

jquery:更好的api;兼容处理。简化js的dom操作

vue:使用mvvm框架,响应式处理,以数据驱动视图,引入了组件化思想,虚拟dom操作等

vue和react:

相同:1.组件化思想;2.虚拟dom;3.数据驱动视图;4.支持服务端渲染

不同:1.双向与单向数据流;2.diff算法不同(vue对比dom,之后统一批量更新dom,react使用双指针,边对比边更新);3.组件通信方式(vue使用事件和回调函数,react使用回调函数)

7.Vue 如何实现响应式

1.vue通过属性保存选项数据,把data转换成getter/setter,注入到vue实例

2.实现observer数据劫持,监听数据的变化。defineProperty,proxy

3.进行compiler解析,编译模版,处理文本节点和元素节点

4.实现一个依赖收集器dep,添加依赖并且通知观察者

5.watcher观察者在实例化的时候往dep对象中添加自己,数据变化后更新视图

发布/订阅者模式

8.Vue 组件通信

每个组件都有各自的作用域,组件内的数据是无法共享的,但是在开发过程中我们常常会想让组件之间共享数据

1.父子组件之间的通信

  • 父组件使用props传递数据,子组件通过$emit触发事件
  • ref:父组件在使用子组件的时候使用ref,子组件通过设置的ref值来获取数据

2.兄弟组件之间的通信

  • 中央事件总线EventBus:$emit触发,$on监听
  • 通过共同祖辈$parent 或者 $root牵线搭桥。this.$parent.emit/on(与EventBus用法相似)

3.祖先与后代组件之间的通信

  • project和inject: 在祖先组件定义`provide`属性,返回传递的值 在后代组件通过`inject`接收组件传递过来的值
  • $attrs 与$ listeners:v-bind=”$attrs”传入内部组件

4.无关联组件之间的通信

vuex:一个用来存储共享变量的容器

9.Vuex 属性有哪些

  • state:用来存放共享变量
  • getter:用来获取共享变量的值
  • mutation:用来存放修改state的同步方法 存储的方法eg:setData(state, 参数payload(可选,建议对象)) {} 触发方法:this.$store.commit(‘setData’, {});
  • action:也是存放修改state的方法,不过是在mutation的基础上进行,常做一些异步操作 在内部触发mutation,方法的第一个参数为复制的store,可以直接用当前参数.commit() 触发方法:this.$store.dispatch(‘setNum’)

定义在state中的变量可以通过this.$store.state.xxx访问

定义在getter中的同样也可以使用this.$store.getters.xxx访问

优雅起见,我们使用mapState、mapGetters、mapMutations、mapActions去解构到计算属性中

import { mapState, mapGetters, mapMutations,mapActions} from ‘vuex’ 这样就可以直接用this进行访问啦,还可以取别名

原理总结:

Vuex的双向绑定通过调用 new Vue实现,然后通过 Vue.mixin 注入到Vue组件的生命周期中,再通过劫持state.get将数据放入组件中

10.Vue2、Vue3 生命周期

vue2生命周期:

beforeCreate:初始化vue,进行数据监测

created:完成数据监测,属性和方法的计算,此时$el并没有被创建

beforeMount:虽然已经完成dom初始化,但未挂载到el选项上

mounted:完成挂载与渲染

beforeUpdate,updated,beforeDestroy,destroyed

activated/deactivated/errorCaptured

vue3生命周期

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

在CompositionAPI中,需要将生命周期钩子函数导入在项目中,才能使用,beforeCreated和created被setup方法所取代

11.Vue-router 导航有哪些

使用步骤:

1.vue.use注册路由组件

2.创建路由对象,同时需要把路由规则导出

3.main中注册router对象

4.创建路由组件的占位<router-view/>

5.创建链接<router-link></router-link>

钩子函数(导航守卫):

全局守卫:

全局前置守卫:router.beforeEach((to,from,next)⇒{}),可定义多个守卫

全局解析守卫:router.beforeResolve

全局后置钩子:router.afterEach,全局跳转之后,不接受next参数,也不改变导航本身

路由守卫:路由相关的钩子

beforeEnter: (to, from) => {}

组件守卫:定义在组件内部的守卫

beforeRouteEnter:该守卫内访问不到组件的实例,即 this 为 undefined,在 beforeCreate 生命周期前触发

beforeRouteUpdate:没有next方法

beforeRouteLeave:没有next方法

动态路由的实现方式:

1.通过当前路由规则获取:$route.params.id

2.路由规则中开启props传参,组件中接收参数:props:true

编程式导航:this.$router.push();this.$router.replace()(不记录本次历史);this.$router.go(-1)

hash和history模式的区别:

1.表现形式:#、?等无关字符 vs /

2.原理:

hash:基于锚点(改变锚点,监听锚点变化),监听hashchange事件

history:改变url,基于H5的history API(pushState、replaceState)当调用这两个方法的时候,url会发生变化,浏览器访问历史也会发生变化,但是浏览器不会向后台发送请求。

可以通过监听popstate事件监听history变化,根据path不同渲染不同的dom

history模式的启用:设置mode:history;需要服务器支持(vue-cli服务器配置好了)

如果访问的url不存在,就将单页应用默认的index.html返回给浏览器

实现原理核心:

通过Vue.use注册插件,在插件的install方法中获取用户配置的router对象。当浏览器地址发生变化的时候,根据router对象匹配相应路由,获取组件,并将组件渲染到视图上

12.Vue3 有什么新特性

vue2面临的问题:

1.功能的增长,复杂组件变得越来越难维护

2.缺少一个比较纯粹的能在多个组件中提取和复用逻辑的机制

3.类型推断不够友好

新特性:

TypeScript支持

CompositionAPI

vue2:optionAPI的代码编写方式,每个组件都有自己的method,data等等,组件内会有很多逻辑关注点,在使用mixin去复用相同的逻辑的时候,存在两个很重要的问题:命名冲突,数据来源不清晰。

定义:组件根据逻辑功能来组织,一个功能所定义的所有api会放在一起。高内聚,低耦合。使用setup()获取api里的内容,数据来源清晰,没有命名冲突。几乎都是使用函数的形式,tree-shaking支持,不使用this,减少了this指向不明的问题。适合大型组件使用

性能提升:

数据劫持优化

diff算法优化(为会发生变化的地方增加一个flag静态标记)

静态提升(对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用)

更小:

移除了一些不常用的API

tree-shaking

  • 编译阶段利用ES6 Module判断哪些模块已经加载
  • 判断那些模块和变量未被使用或者引用,进而删除对应代码

源码结构更清晰,以模块划分

vite配套打包工具

  • 基于远程ES module来开发,省略了打包步骤(浏览器支持原生的模块化导入)
  • 快速的冷启动和模块热更新
  • 真正的按需编译(只在需要的时候动态import,不需要提前打包,适用开发环境)

13.对 TypeScript 的认识

typescript并不是一门新的语言,而是js的超集,解决了js类型系统的问题,并最终编译成js代码

1.它可以在代码编译阶段发现并纠正错误

2.强类型语言(限制实参类型,更强的类型约束,不允许任何形式的隐式类型转换),可静态可动态

3.支持模块,泛型和接口

是一门渐进式的语言,可以增强代码的可读性和可维护性

14.对 class、interface 的认识

class:类,是面向对象实现信息封装的基础,ts中的class支持面向对象中的所有特性

包含:类中定义的变量,构造函数和方法

可以使用extends关键字实现继承。类继承后子类可以对父类的方法进行重写,super关键字是对父类的直接引用。

typescript中在此基础上添加了三种访问修饰符:

private:私有属性

public:公共

protect:只允许在子类中访问,可被继承

还有只读修饰符:readonly

静态属性:static,存在于类本身,而不是在类的实例上

抽象类:不能被实例化,通常需要我们创建子类去继承。一般用来约束子类中必须有某种成员

应用场景:使用类的特性完成一些业务代码;还可以将类作为接口,方便统一管理

interface:接口。是一种规范和契约,约定对象成员以及类型,约束对象结构。

固定成员,可选成员,只读成员,动态成员。接口还可以实现继承,如果继承多个父类只需要,分隔

应用:在一个函数中需要用到一些参数,如果这个函数在多处调用没有注释的话,就有可能出现运行时错误,这个时候就可以使用接口

15.前端页面如何优化

(1)更快的网络通信

1.DNS解析层面:使用cdn(全局负载均衡和主服务器缓存系统)

2.服务器通信层面:减少http请求次数(资源合并)tcp连接限制(域名分片)-http2中均不推荐

3.数据传输层面:缓存(开启强缓存和协商缓存),压缩(gzip数据压缩,代码文件,静态资源,请求响应报文等)

4.通信协议层面:http2.0

(2)更高效的数据处理

    1.前端代码层面

       **减少作用域查找和闭包**

       使用**块级作用域**

       多使用**伪元素,**减少访问层级

      使用**语义化标签**增强dom解析

      减少**重绘和回流**

      进行**防抖与节流**

16.跨域如何处理

1.JSONP模拟script标签发起请求。非同源策略的方式。因为script、link、img标签没有同源限制,仅支持get请求

2.CORS,服务端设置 Access-Control-Allow-Origin。分为简单请求(get,post,head)和复杂请求,复杂请求在通信前会增加一次http查询请求,预检(option),来确定服务器是否允许跨域。

3.iframe通过postMessage跨域

4.websocket协议。基于tcp连接,但是连接之后不受http协议的控制,可直接双向通信

5.ngnix反向代理

6.nodejs中间件代理。中间代理服务器先接受客户端请求,然后将请求转发给服务器,拿到服务器 响应数据再转发给客户端。服务器与服务器之间并不会存在跨域行为。webpack-dev-server就是使用这种形式:node express应用框架搭建中间件

17.axios 如何修改 headers?如何通过 axios 拦截器实现请求防抖

axios:基于XMLHttpRequest来实现http请求,有非常丰富的配置,支持promise,浏览器和node

可以拦截请求和响应。进行请求和响应数据转换

如何封装:

1.先和后台约定好一些规范,比如请求头,状态码,超时时间等

2.设置接口请求的前缀baseUrl,区分好开发、测试和生产环境,开发需要配置dev-server

3.设置请求头:普适性的请求头作为基础配置,特殊请求头作为参数传入覆盖基础配置

4.设置状态码:根据不同的code来执行不同的业务操作

5.请求方法:对于get,post等不同的请求方法做相应的封装,并export暴露出去,api统一管理接口

6.设置请求拦截器:根据请求头的设定,来决定哪些请求可以访问

axios(或实例).interceptors.request.use((config)⇒{})

7.设置响应拦截器:根据code不同做不同的业务处理(登录状态,授权等)

请求头的配置:

  • 创建axios实例的时候初始化一份:const instance = axios.create({timeout:xxx,} headers: {})
  • 在请求拦截器之前通过config.header.xxx来设置

拦截器实现防抖:

判断重复请求并存储进队列中

  • 使用map对象存储,只要请求地址,请求方式,请求参数一样我们就可以认为是一样的
  • 储存每个请求的值,也就是cancel方法,用于取消请求,cancelToken
  • 在请求拦截器中执行取消重复请求并删除队列,并添加当前请求的值
  • 在响应拦截器中将该请求删除队列

18.缓存(强缓存、协商缓存)如何设置

缓存优点: 1.减少重复的服务器请求,节省流量 2.降低服务器压力,提高网站性能 3.提升客户端加载速度,提升用户体验 区别: 1.如果命中强缓存,则不需要与服务器通信;而协商缓存最终由服务器来决定是否使用缓存,存在一次通信 2.chrome命中强缓存,会返回200 from cache(disk cache/memory cache快),命中协商缓存是304(not modified)不同浏览器表现不一致,firefox中from cache状态码是304

浏览器请求流程: 1.浏览器在加载资源时,根据请求头的expires和cache-control判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器 2.如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过last-modified和etag验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源 3.若都未命中,直接从服务器加载资源

请求头名词解释: Expires:是http1.0提出的一个表示资源过期时间的header,由服务器返回,受限于本地时间,如果本地时间修改则缓存失效 Cache-Control:http1.1提出的相对时间,eg:max-age=3600 代表资源的有效期是 3600 秒 其他设置项:no-store、no-cache、public、private(只能被终端浏览器)

优先级: Cache-Control > expires > Etag > Last-Modified Last-Modified:标记最后文件修改时间。浏览器会在request header加上If-Modified-Since(上次返回的Last-Modified的值),询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来 Etag:由服务器为每一个资源生成的唯一标识串(hash),只要资源有变化就这个值就会改变。接收到 If-None-Match 字段以后,服务器通过比较两者是否一致来判定文件内容是否被改变

etag解决了Last-Modified什么问题: 1.一些文件也许会周期性的更改,但是内容并不改变 2.文件修改频繁,在秒级以内 3.某些文件服务器不能精确得到文件的最后修改时间

强缓存设置: 后端服务器代码逻辑:res.setHeader(‘Cache-Control ’,‘max-age=3600’) expires同 ngnix配置:add_header Cache-Control “max-age=3600”

协商缓存设置:

1.last-modified,服务器设置last-modified请求头后,浏览器请求同一资源会带if-modified-since头,所以服务端还要获取这个请求头的时间进行对比 2.etag,服务器设置etag请求头(通过md5或者sha1或sha256算法生成hash)浏览器请求同一资源会带if-none-match头,服务端需要或者两次的etag是否一致 Ctrl + F5 强制刷新的时候,会暂时禁用强缓存和协商缓存,从服务器加载资源

19.对 webpack 的理解

webpack是一个模块化的打包工具,解决的是前端整体的模块化。webpack可根据文件输入的依赖关系打包为html、css、js以及各种资源文件

webpack运行在nodejs环境下,配置文件遵循commonjs规范

Webpack在启动后,会从entry开始,递归解析entry依赖的所有Module,每找到一个Module,就会根据Module.rules里配置的Loader规则进行相应的转换处理,对Module进行转换后,再解析出当前Module依赖的Module,这些Module会以entry为单位进行分组,即为一个Chunk。因此一个Chunk,就是一个entry及其所有依赖的Module合并的结果。最后Webpack会将所有的Chunk转换成文件输出Output。在整个构建流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑,从而完成Plugin插件的优化任务。

20.如何通过 webpack 插件获取所有文件名

// 读取输出资源、代码块、模块及其依赖,修改输出资源
**compiler.plugin('emit', function(compilation, callback)** {
	// 处理逻辑
	// ...
	// compilation.chunks 存放所有代码块,是一个数组
	// 读取名称为 fileName 的输出资源
  const asset = **compilation.assets**[fileName];
  // 获取输出资源的内容
  asset.source();
	callback()
})
// 监听文件变化
compiler.plugin('watch-run', (watching, callback) => {
    // 获取发生变化的文件列表
    const changedFiles = watching.compiler.watchFileSystem.watcher.mtimes;
    // changedFiles 格式为键值对,键为发生变化的文件路径。
    if (changedFiles[filePath] !== undefined) {
      // filePath 对应的文件发生了变化
    }
    callback();
});

21.http1.1 与 http2 的区别

http1.1的性能瓶颈: 1.头部比较大,没有压缩 2.支持一个tcp连接发送多个请求,因为请求本身有顺序,所以返回也需要有先后顺序,不然对应不上,只是节省了一些tcp连接的时间,限制还是比较多 3.服务器响应慢会导致队头堵塞 3.只支持客户端发起连接

http2.0: 1.启用了头部压缩(hpack压缩算法) 2.支持多路复用,一个连接并发多个请求,无需限制顺序(之前的协议都是以文本的形式,2.0是以二进制桢的形式)每个http请求被切分成多帧,多个http的帧混合在一起在一个tcp连接上传送。请求发送之后,服务器处理需要一定时间,这段空档期再利用

3.允许服务器推送消息

22.nginx 负载均衡

一种调度策略,如果单个服务器出现故障,负载均衡的方法会将流量重定向到其余的集群服务器,以保证服务的稳定性。当新的服务器添加到服务器组后,也可通过负载均衡的方法使其开始自动处理客户端发来的请求。

正向代理:客户端非常明确想要访问的服务器地址,请求代理服务器,替客户端发送请求。这个过程中服务器并不知道发起请求的是谁

反向代理:反向代理隐藏了服务器的信息,它代理的是服务器端。客户端并不知道具体哪台服务器处理了自己的请求

反向代理需要考虑的问题是,如何进行均衡分工,控制流量,避免出现局部节点负载过大的问题

ngnix是基于c语言的高性能web服务器

负载均衡常用算法:轮询(遍历服务器节点列表),加权轮询(遍历的基础上添加weight,性能好的情况下多分配一些)

原创文章,作者:站长,如若转载,请注明出处:https://wsppx.cn/1807/%e7%bd%91%e7%bb%9c%e5%bc%80%e5%8f%91/%e5%89%8d%e7%ab%af/

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注