http协议等内容

注:资料来源于网络,省得到处找

TCP冷启动:

TCP连接有一个预热和保护的过程,先检查数据是否传送成功,一旦成功过,则慢慢加大传输速度。因此对应瞬时并发的连接,服务器的响应就会变慢。所以最好能使用一个建立好的连接,并且这个连接可以支持瞬时并发的请求。

HTTP1.1

1、长连接
在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。
一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍
然需要使用各自的连接。HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器
端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样
也显著地减少了整个下载过程所需要的时间。基于HTTP 1.1协议的客户机与服务器的信息交换过程。

2、丰富缓存
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了
更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match,
If-None-Match等更多可供选择的缓存头来控制缓存策略。

3、节约带宽
HTTP 1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,
否则返回401。客户端如果接受到100,才开始把请求body发送到服务器。
这样当服务器返回401的时候,客户端就可以不用发送请求body了,节约了带宽。
另外HTTP还支持传送内容的一部分。这样当客户端已经有一部分的资源后,只需要跟服务器请求另外的部分资源即可。这是支持文件断点续传的基础。

4、host域
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。

5、丰富报错码
在HTTP1.1中新增了24个错误状态响应码。

HTTP2.0

1、多路复用
所有的HTTP2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流。
每个数据流以消息的形式发送,而消息由一或多个帧组成。这些帧可以乱序发送,然后再根据每个帧头部的流标识符(stream id)重新组装。

举个例子,每个请求是一个数据流,数据流以消息的方式发送,而消息又分为多个帧,帧头部记录着stream id用来标识所属的数据流,不同属的帧可以在连接中随机混杂在一起。接收方可以根据stream id将帧再归属到各自不同的请求当中去。

另外,多路复用(连接共享)可能会导致关键请求被阻塞。HTTP2.0里每个数据流都可以设置优先级和依赖,优先级高的数据流会被服务器优先处理和返回给客户端,数据流还可以依赖其他的子数据流。
可见,HTTP2.0实现了真正的并行传输,它能够在一个TCP上进行任意数量HTTP请求。而这个强大的功能则是基于“二进制分帧”的特性。

2、头部数据压缩
在HTTP1.1中,HTTP请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,消息主体都会经过gzip压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着Web功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输UserAgent、Cookie这类不会频繁变动的内容,完全是一种浪费。
HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。

3、服务器推送
当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。
服务器端推送的这些资源其实存在客户端的某处地方,客户端直接从本地加载这些资源就可以了,不用走网络,速度自然是快很多的。

UDP和TCP的区别

1、连接方面区别
TCP面向连接(如打电话要先拨号建立连接)。
UDP是无连接的,即发送数据之前不需要建立连接。

2、安全方面的区别
TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达。
UDP尽最大努力交付,即不保证可靠交付。

3、传输效率的区别
TCP传输效率相对较低。
UDP传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。

4、连接对象数量的区别
TCP连接只能是点到点、一对一的。
UDP支持一对一,一对多,多对一和多对多的交互通信。

TCP 是面向字节流(流模式)的,UDP 是基于数据报的

MySql 基本指令

不做后端开发,不常操作数据库,很容易忘记。记录下自己用到过几条数据库命令。(持续)

连上数据库

// -u 指向用户, -p 需要密码
mysql -u root -p

显示数据库

show databases;

创建数据库

create database 数据库名字;

删除数据库

drop table 数据库名字;

选择数据库

use 数据库名字;

显示表

show tables;

创建表

create table 表名字;

删除表

drop table 表名字;

查看表结构

show create table 表名字;

查看表内容

select * from 表名字;

查看表条数

select count(*) from 表名字;

查看表索引

show index table 表名字;

清空表

truncate table 表名字;

更新数据,注意搜索的值字符串的话要加引号

update table_name set 要更新的字段=要更新的值 where 搜索的字段=搜索的值;

设置密码

// set password for 用户名@localhost = password(‘新密码’);
set password for root@localhost = password('123456');

更新数据是从另外一张表拿的值

update 表A,表B set 表A.字段A=表B.字段A where 表A.字段B=表B.字段B and 表A.字段A=字段值;

增加字段名

// 字段类型可以先看表结构参考其他字段 show create table 表名字;
alter table 表名 add 字段名 字段类型 default 默认值;

JS性能优化探讨

一、最核心一点,减少http请求,3次握手,冷启动,成本昂贵

  1. 合并小js文件
  2. 使用雪碧图
  3. 小图转换成base64放到代码里
  4. 设置缓存

二、加快响应

  1. CDN
  2. 减少DNS查询次数
  3. 提前加载,延迟加载
  4. 首页最小内容显示,将样式表置顶渲染页面,将js放到底部不阻塞页面渲染。

三、资源层面

  1. 能用不那么高清图片,就用体积小的图片
  2. 压缩业务代码
  3. 压缩减少或不要cookie,每次请求头都会带上
  4. 把静态资源放在另外一个域名,根据域名划分内容。
    浏览器一般对同一个域的下载连接数有所限制,按照域名划分下载内容可以浏览器增大并行下载连接。
    但是注意控制域名使用在2-4个之间,不然dns查询也是个问题。
    一般网站规划会将静态资源放在类似于static.example.com,动态内容放在www.example.com上。
    这样做还有一个好处是可以在静态的域名上避免使用cookie。页面内容使用无cookie域名
  5. 使用小且可缓存的favicon.ico网站图标文件favicon.ico。
    不管你服务器有还是没有,浏览器都会去尝试请求这个图标。所以我们要确保这个图标存在文件尽量小,最好小于1k设置一个长的过期时间

四、代码层面

  1. html尽量减少dom的数量(可以 document.getElementsByTagName(‘*’).length 查看有多少个)
  2. 避免CSS表达式,CSS表达式的问题在于它被重新计算的次数远比我们想象的要多,不仅在网页绘制或大小改变时计算,即使我们滚动屏幕或者移动鼠标的时候也在计算,因此我们还是尽量避免使用它来防止使用不当而造成的性能损耗。
  3. 减少对dom的操作
  4. 代替@import,避免使用@import的原因很简单,因为它相当于将css放在网页内容底部。
  5. 使用智能事件处理
    这里说智能的事件处理需要开发者对事件处理有更深入的了解,通过不同的方式尽量少去触发事件,如果必要就尽早的去处理事件。比如一个div中10个按钮都需要事件句柄,那么我们可以将事件放在div上,在事件冒泡过程中捕获该事件然后判断事件来源。

JS 事件循环

web:

1、
浏览器有多线程,GUI渲染线程,定时器线程,IO线程(ajax)线程,事件触发线程,js线程。
2、
对于js而言,是单线程,一条线走到底。其他线程都是异步任务,处理把回调推入任务队列。
3、
js开始运行,把同步任务一个个入栈执行,这其中由于同步任务产生的异步回调都进入
任务队列了。执行完毕后,栈空。开始查询异步队列,一个个压入栈再执行,直至清空队列,其中过程再产生异步任务再次推入异步队列。不断循环的检查任务队列,执行任务队列的任务,压入任务队列。
其中任务队列有细分有宏任务,微任务。
4、
优先执行微任务,并且微任务清一列,宏任务清一个。
5、
同步任务执行可以看做第一个宏任务执行完毕。接着清空微任务队列,清一个宏任务,接着再清空微任务队列,再继续清一个宏任务,不断循环,直到没有,也可以看成微任务只有一列但是一列有多个,宏任务有多列但是一列只有一个。这是js的事件循环机制。
6、
属于微任务(microtask)的事件有以下几种:
Promise.then
MutationObserver
Object.observe
process.nextTick
7、
属于宏任务(macrotask)的事件有以下几种:
setTimeout
setInterval
setImmediate
MessageChannel
requestAnimationFrame
I/O
UI交互事件

setTimeout(() => {
  console.log('宏任务--1')
  Promise.resolve()
  .then(() => {
    console.log('微任务2--1')
  })
  .then(() => {
    console.log('微任务2--2')
    setTimeout(() => {
      console.log('宏任务--3')
    })
  })
})
console.log('同步任务--1')

new Promise((resolve) => {
  console.log('同步任务--2')
  resolve()
}).then(() => {
  console.log('微任务1--1')
})

Promise.resolve().then(() => {
  console.log('微任务1--2')
})
setTimeout(() => {
  console.log('宏任务--2')
  Promise.resolve().then(() => {
    console.log('微任务3--1')
  })
  setTimeout(() => {
    console.log('宏任务--4')
  })
})
console.log('同步任务--3')
console.log('同步任务--4')


Node:

https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/

1、
node的事件分阶段来循环,
timers -> IO callbacks -> idle, prepare -> poll(incoming) -> check -> close
2、
入口在poll阶段,每个阶段都有自己的队列
3、
__定时器:__本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。
__待定回调:__执行延迟到下一个循环迭代的 I/O 回调。
__idle, prepare:__仅系统内部使用。
__轮询:__检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞。
__检测:__setImmediate() 回调函数在这里执行。
__关闭的回调函数:__一些关闭的回调函数,如:socket.on(‘close’, …)。
4、
轮询(poll)阶段有两个重要的功能:
计算应该阻塞和轮询 I/O 的时间。
然后,处理 轮询 队列里的事件。
这里会循环到清楚队列任务,或者达到node限制
5、
每个阶段结束都会查询清空process.nextTick的回调队列

const fs = require('fs')
fs.readFile('lib.js', () => {
  setTimeout(() => {
    console.log('cb setTimeout--1')
  }, 0)
  setImmediate(() => {
    console.log('cb setImmediate--1')
  })
})

process.nextTick(() => {
  console.log('nextTick--1')
})
setImmediate(() => {
  console.log('setImmediate--1')
})
setTimeout(() => {
  console.log('setTimeout--1')
  process.nextTick(() => {
    console.log('nextTick--3')
  })
}, 0)
console.log('script--1')

Promise.resolve().then(() => {
  console.log('resolve then--1')
})
new Promise((resolve) => {
  console.log('Promise--1')
  resolve()
}).then(() => {
  console.log('then--1')
  process.nextTick(() => {
    console.log('nextTick--3')
  })
})

setTimeout(() => {
  console.log('setTimeout--2')
  Promise.resolve().then(() => {
    console.log('setTimeout -- resolve then--1')
  })
  setImmediate(() => {
    console.log('setImmediate--3')
  })
}, 0)
console.log('script--3')
console.log('script--4')

process.nextTick(() => {
  console.log('nextTick--2')
  setImmediate(() => {
    console.log('setImmediate--2')
  })
})


补充

宿主环境提供的叫宏任务,由语言标准提供的叫微任务。

宏任务每次执行一个的原因:浏览器为了能够使得JS内部task与DOM任务能够有序的执行,会在一个task执行结束后,在下一个 task 执行开始前,对页面进行重新渲染 (task->渲染->task->…)

参考:https://segmentfault.com/a/1190000014940904?utm_source=tag-newest

JS new 一个对象干了什么事


function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.attr = 'human'
const man1 = new Person('123', 18)
console.log(man1.name)
console.log(man1.age)
console.log(man1.attr)

function _new(Constructor, ...param) {
  // 新建一个对象
  const obj = {} // Object.create(null)
  // 建立继承关系,__proto__指向构造函数原型,获得原型属性与方法
  // 这里获得 attr 属性
  obj.__proto__ = Constructor.prototype
  // 开始执行这个构造函数,就是这个构造函数的this方法属性挂到这个新对象上
  // 这里就是把 name 和 age 挂上去
  const ret = Constructor.call(obj, ...param)
  // const ret = Constructor.apply(obj, param)
  // 若构造函数中没有返回值或返回值是基本类型(Number、String、Boolean)的值,则返回新实例对象;
  // 若返回值是引用类型的值,则实际返回值为这个引用类型。
  return typeof ret === 'object' ? ret : obj
}
const man2 = _new(Person, '456', 20)
console.log(man2.name)
console.log(man2.age)
console.log(man2.attr)