获得徽章 0
- #青训营笔记创作活动#
二月十一日 打卡day 21
今日学习 高并发下秒杀商品,你必须知道的9个细节
瞬时高并发
像这种瞬时高并发的场景,传统的系统很难应对,我们需要设计一套全新的系统。可以从以下几个方面入手:
页面静态化
CDN加速
缓存
mq异步处理
限流
分布式锁
2. 页面静态化
活动页面绝大多数内容是固定的,比如:商品名称、商品描述、图片等。为了减少不必要的服务端请求,通常情况下,会对活动页面做静态化处理。用户浏览商品等常规操作,并不会请求到服务端。只有到了秒杀时间点,并且用户主动点了秒杀按钮才允许访问服务端
3 秒杀按钮
从前面得知,该活动页面是静态的。那么我们在静态页面中如何控制秒杀按钮,只在秒杀时间点时才点亮呢?使用js文件控制。为了性能考虑,一般会将css、js和图片等静态资源文件提前缓存到CDN上,让用户能够就近访问秒杀页面。
4 读多写少
因为数据库的连接资源非常有限,比如:mysql,无法同时支持这么多的连接。而应该改用缓存,比如:redis。即便用了redis,也需要部署多个节点。
5 缓存问题
5.1 缓存击穿
最好使用分布式锁
5.2 缓存穿透
布隆过滤器展开评论点赞 - #青训营笔记创作活动#
二月九日 打卡day 20
今日学习 为什么我抓不到baidu的数据包
为什么没能抓到包
这其实是因为他访问的是HTTPS协议的baidu.com。HTTP协议里的Host和实际发送的request body都会被加密。
怎么得到pre_master_key
客户端在使用HTTPS与服务端进行数据传输时,是需要先基于TCP建立HTTP连接,然后再调用客户端侧的TLS库(OpenSSL、NSS)。触发TLS四次握手。
这时候如果加入环境变量SSLKEYLOGFILE就可以干预TLS库的行为,让它输出一份含有pre_master_key的文件。这个文件就是我们上面提到的/Users[obaidebug/ssl.key。
总结
文章开头通过抓包baidu的数据包,展示了用wireshark抓包的简单操作流程。
HTTPS会对HTTP的URL和Request Body都进行加密,因此直接在filter栏进行过滤http.host == "baidu.com"会一无所获。
HTTPS握手的过程中会先通过非对称机密去交换各种信息,其中就包括3个随机数,再通过这三个随机数去生成对称机密的会话秘钥,后续使用这个会话秘钥去进行对称加密通信。如果能获得这三个随机数就能解密HTTPS的加密数据包。
三个随机数,分别是客户端随机数(client random),服务端随机数(server random)以及pre_master_key。前两个,是明文,第三个是被服务器公钥加密过的,在客户端侧需要通过SSLKEYLOGFILE去导出。
通过设置SSLKEYLOGFILE环境变量,再让curl或chrome会请求HTTPS域名,会让它们在调用TLS库的同时导出对应的sslkey文件。这个文件里包含了三列,其中最重要的是第二列的client random信息以及第三列的pre_master_key。第二列client random用于定位,第三列pre_master_key用于解密。
展开评论点赞 - #青训营笔记创作活动#
二月八日 打卡day 19
今日学习 涨姿势了,这 4 个场景可用 CSS 完全取代 JS ~
1. 颜色选择器
<input type="color" value="#FF99FF" />
2. 打字效果
<h1>Welcome to JUEJIN</h1>
@-webkit-keyframes typing { from { width: 0; } }
@-webkit-keyframes blink-caret { 50% { border-color: transparent; } }
h1 {
font: bold 300% Consolas, Monaco, monospace;
border-right: .1em solid black;
width: 16.5em;
width: 21ch;
margin: 2em 1em;
white-space: nowrap;
overflow: hidden;
-webkit-animation: typing 7s steps(21, end),
blink-caret .5s step-end infinite alternate;
}
3. 滑顶/触底效果
<a id="top" href="#bottom">Scroll to bottom</a>
<div>
<p>hello JUEJIN</p>
<p>hello JUEJIN</p>
<p>hello JUEJIN</p>
<p>hello JUEJIN</p>
</div>
<a id="bottom" href="#top">Scroll to top</a>
4. 顺滑切图
原来 CSS scroll-snap-type: x mandatory; 可以让你顺滑切图展开评论点赞 - #青训营笔记创作活动#
二月五日 打卡day 18
今日学习 20个常用的 Git 指令用法
it 分为 4 个工作区
git clone
git clone 命令用于将存储库克隆到本地。
git init
git init 命令用于在目录中创建新的 Git 仓库。
git remote
git remote 用于管理跟踪远程仓库。
git checkout
git checkout 命令用于切换分支。
git branch
git branch 命令用于查看、创建、删除分支。
git tag
git tag 用于创建、删除、查看标签。
git add
git add 命令用于将本地文件添加到暂存区。
git commit
git commit 命令用于将暂存区内容添加到本地仓库中。
git push
git push 命令用于将本地分支推送到远程仓库。
git pull
git pull 命令用于从远程仓库拉取代码并合并到本地当前分支。
git fetch
git fetch 命令用于从远程获取代码库。
git cherry-pick
git cherry-pick 命令用于获取指定的 commit,可以将分支 a 上的 commit 1,复制到分支 b上。
git merge
git merge 命令用于分支合并,将其他分支的内容合并到当前分支中。
git rebase
git rebase 用于分支变基。
git rebase -i 交互模式:
git rebase -i [commitId] // 基于 commitId 进行 rebase,交互式变基,可以重新编辑 commit,比如压缩合并
git reset
git reset 命令用于回退版本,可以指定退回某一次提交的版本。
git revert
git revert 指令用于回滚提交,可以回滚某一次提交记录。
git stash
git stash 用于暂存文件。
git reflog
git reflog 记录了所有的 commit 操作记录,便于错误操作后找回。
git rm
git rm 用于从 git 仓库删除指定文件或目录。
git log
git log 命令用于查看 git commit 记录。展开评论点赞 - #青训营笔记创作活动#
二月五日 打卡day 17
今日学习 不使用第三方库怎么实现【前端引导页】功能?
第三方库的选择
vue-tour
vue-tour 是一个轻量级、简单且可自定义的 Tour 插件,配置也算比较简单清晰,但只适用于 Vue2 的项目,具体效果可以直接参考对应的前面链接对应的内容。
driver.js
driver.js 是一个强大而轻量级的普通 JavaScript 引擎,可在整个页面上驱动用户的注意力,只有 4kb 左右的体积,并且没有外部依赖,不仅高度可定制,还可以支持所有主流浏览器。
shepherd.js
shepherd.js 包含的 API 众多,大多场景都可以通过其对应的配置得到,缺点就是整体的包体积较大,并且配置也比较复杂,配置复杂的内容一般都需要进行二次封装,将可变和不可变的配置项进行抽离,具体效果可见其 官方文档。
intro.js
intro.js 是是一个开源的 vanilla Javascript/CSS 库,用于添加分步介绍或提示,大小在 10kB左右,属于轻量级的且无外部依赖,详情可见 官方文档。
展开评论点赞 - #青训营笔记创作活动#
二月四日 打卡day 16
今日学习 提升代码可读性,减少if-else的几个小技巧
Javascript 的逻辑或 || 的短路运算有时候可以用来代替一些比较简单的 if else
多时候简单的一些判断我们都可以使用三元运算符去替代 if else,这里只推荐 一层 三元运算符,因为多层嵌套的三元运算符也不具备良好的可读性🥹
短路运算跟三元运算虽然很好用,代码也很简洁,不过都只能用于简单的判断,遇到多重条件判断就不能使用了。
对于 switch case,虽然它的可读性确实比 else if 更高,但是我想大家应该都觉得它写起来比较麻烦吧
对象配置/策略模式展开评论点赞 - #青训营笔记创作活动#
二月二日 打卡day 15
今日学习 Qiankun原理——JS沙箱是怎么做隔离的
SanpshotSandbox
第一种是快照沙箱,它的原理是:把主应用的 window 对象做浅拷贝,将 window 的键值对存成一个 Hash Map。之后无论微应用对 window 做任何改动,当要在恢复环境时,把这个 Hash Map 又应用到 window 上就可以了。
LegacySandbox
LegacySandbox 的想法则是 通过监听对 window 的修改来直接记录 Diff 内容,因为只要对 window 属性进行设置,那么就会有两种情况:
如果是新增属性,那么存到 addedMap 里
如果是更新属性,那么把原来的键值存到 prevMap,把新的键值存到 newMap
(当然这里的变量名做了简化)
通过 addedMap, prevMap 和 newMap 这三个变量就能反推出微应用以及原来环境的变化,qiankun 也能以此作为恢复环境的依据。
ProxySandbox
总结
总结一下,qiankun 一共有 3 种沙箱:
SnapshotSandbox:记录 window 对象,每次 unmount 都要和微应用的环境进行 Diff
LegacySandbox:在微应用修改 window.xxx 时直接记录 Diff,将其用于环境恢复
ProxySandbox:为每个微应用分配一个 fakeWindow,当微应用操作 window 时,其实是在 fakeWindow 上操作展开评论点赞 - #青训营笔记创作活动#
二月一日 打卡day 14
今日学习 JavaScript 必须学会的11 个工具方法(避免重复造轮子)
1.计算距离下次生日还有多少天
2.回到顶部
3.复制文本
4.防抖/节流
防抖:指定时间内 频繁触发一个事件,以最后一次触发为准
节流:指定时间内 频繁触发一个事件,只会触发一次
5.过滤特殊字符
6.常用正则判断
7.初始化数组
8.将 RGB 转换为十六进制
9.检测是否是一个函数
10.检测是否为一个安全数组
11.检测对象是否为一个安全对象展开评论点赞 - #青训营笔记创作活动#
一月三十日 打卡day 13
今日学习 前端人70%以上 不了解的promise/async await
1. 早期异步代码困境
2. Promise
Promise(承诺),给予调用者一个承诺,过一会返回数据给你,就可以创建一个promise对象
当我们new一个promise,此时我们需要传递一个回调函数,这个函数为立即执行的,称之为(executor)
这个回调函数,我们需要传入两个参数回调函数,reslove,reject(函数可以进行传参)
当执行了reslove函数,会回调promise对象的.then函数
当执行了reject函数,会回调promise对象的.catche函数
new Promise((resolve, reject) => {
console.log(`executor 立即执行`)
})
好处呢? 看起来比早期处理的方案还要繁琐呢?
1.统一规范,可以增强阅读性和扩展性
2.小幅度减少回调地狱
2.4 resolve不同值的区别
如果resolve传入一个普通的值或者对象,只能传递接受一个参数,那么这个值会作为then回调的参数
如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态
then方法是有返回值的,它的返回值是promise,但是是promise那它的状态如何决定呢?
返回一个普通值,则相当于主动调用Promise.resolve,并且把返回值作为实参传递到then方法中。
如果没有返回值,则相当于返回undefined
Promise.allall方法的参数传入为一个可迭代对象,返回一个promise,只有三个都为resolve状态的时候才会调用.then方法。
只要有一个promise的状态为rejected,则会回调.catch方法
当遇到rejectd的时候,后续的promise结果我们是获取不到,并且会把reject的实参,传递给catch的err形参中
Promise.allSettled
上面的Promise.all有一个缺陷,就是当遇到一个rejected的状态,那么对于后面是resolve或者reject的结果我们是拿不到的
展开评论点赞 - #青训营笔记创作活动#
一月二十九日 打卡day 12
今日学习 在 JavaScript 中,什么时候使用 Map 或胜过 Object
为什么对象不符合 Hash Map 的使用情况
在 Hash Map 中使用对象最明显的缺点是,对象只允许键是字符串和 symbol。任何其他类型的键都会通过 toString 方法被隐含地转换为字符串。
不必要的继承
在ES6之前,获得 hash map 的唯一方法是创建一个空对象:然而,在创建时,这个对象不再是空的。尽管 hashMap 是用一个空的对象字面量创建的,但它自动继承了 Object.prototype。
性能差异
在 JavaScript 社区中,似乎有一个共同的信念,即在大多数情况下,Map 要比 Object 快。有些人声称通过从 Object 切换到 Map 可以看到明显的性能提升。
我在 LeetCode 上也证实了这种想法,对于数据量大的 Object 会超时,但 Map 上则不会。
总结
Map 比 Object 快,除非有小的整数、数组索引的键,而且它更节省内存。
如果你需要一个频繁更新的 hash map,请使用 Map;如果你想一个固定的键值集合(即记录),请使用Object,并注意原型继承带来的陷阱。展开评论点赞