dragon

dragon 查看完整档案

北京编辑  |  填写毕业院校百家互联  |  web前端工程师 编辑 github.com/yulilong/my_blog 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

dragon 收藏了文章 · 9月25日

前端开发常用免费资源,显著提升工作效率

Jatin Rao 原作,授权 New Frontend 翻译。

最近几个月我收集了大量可以显著提升开发效率的资源链接,在这篇文章中我会分享其中一些。这些资源对我很有帮助,希望对你也是如此。闲话少叙,下面是一些很棒的免费资源!

HTML

CSS

JavaScript

  • JavaScript 30 使用原生 JavaScript 在 30 天内完成 30 个项目
  • Codewars 和其他人一起完成真实的代码挑战,提升你的技术
  • ESLint 检测、修正 JavaScript 代码的问题
  • Prettier 格式化 JavaScript 代码

图标

色彩

插画

图片

  • Unsplash 可供免费使用的图片
  • Pexels 精美的免费图片和视频
  • Burst 免费高分辨率图片,可用于网站和商业用途
  • ISO Republic 使用 CC0 许可的免费高分辨率图片和视频
  • Pixabay 令人惊叹的免费(公共领域)图片和视频站点
  • StockSnap.io 精美的免费图片,同样使用 CC0 许可
  • Photopea 在线图片编辑工具,支持大量高级功能
  • Online Image Compressor 在线图片压缩工具,一次可以压缩多达 20 张图片
  • Bulk Resize Photos 最快的在线图片缩放工具(图片缩放和压缩在本地完成,无需上传到服务器)

参考

可访问性

部署

  • GitHub Pages GitHub 提供的免费静态网站托管服务
  • Netlify 30 秒内部署你的网站
  • Vercel 快速部署你的网站
  • Surge 只需一个命令就可以发布你的网站
  • Heroku 在云端构建、运行你的应用

其他

查看原文

dragon 收藏了文章 · 9月25日

前端开发常用免费资源,显著提升工作效率

Jatin Rao 原作,授权 New Frontend 翻译。

最近几个月我收集了大量可以显著提升开发效率的资源链接,在这篇文章中我会分享其中一些。这些资源对我很有帮助,希望对你也是如此。闲话少叙,下面是一些很棒的免费资源!

HTML

CSS

JavaScript

  • JavaScript 30 使用原生 JavaScript 在 30 天内完成 30 个项目
  • Codewars 和其他人一起完成真实的代码挑战,提升你的技术
  • ESLint 检测、修正 JavaScript 代码的问题
  • Prettier 格式化 JavaScript 代码

图标

色彩

插画

图片

  • Unsplash 可供免费使用的图片
  • Pexels 精美的免费图片和视频
  • Burst 免费高分辨率图片,可用于网站和商业用途
  • ISO Republic 使用 CC0 许可的免费高分辨率图片和视频
  • Pixabay 令人惊叹的免费(公共领域)图片和视频站点
  • StockSnap.io 精美的免费图片,同样使用 CC0 许可
  • Photopea 在线图片编辑工具,支持大量高级功能
  • Online Image Compressor 在线图片压缩工具,一次可以压缩多达 20 张图片
  • Bulk Resize Photos 最快的在线图片缩放工具(图片缩放和压缩在本地完成,无需上传到服务器)

参考

可访问性

部署

  • GitHub Pages GitHub 提供的免费静态网站托管服务
  • Netlify 30 秒内部署你的网站
  • Vercel 快速部署你的网站
  • Surge 只需一个命令就可以发布你的网站
  • Heroku 在云端构建、运行你的应用

其他

查看原文

dragon 赞了文章 · 9月25日

前端开发常用免费资源,显著提升工作效率

Jatin Rao 原作,授权 New Frontend 翻译。

最近几个月我收集了大量可以显著提升开发效率的资源链接,在这篇文章中我会分享其中一些。这些资源对我很有帮助,希望对你也是如此。闲话少叙,下面是一些很棒的免费资源!

HTML

CSS

JavaScript

  • JavaScript 30 使用原生 JavaScript 在 30 天内完成 30 个项目
  • Codewars 和其他人一起完成真实的代码挑战,提升你的技术
  • ESLint 检测、修正 JavaScript 代码的问题
  • Prettier 格式化 JavaScript 代码

图标

色彩

插画

图片

  • Unsplash 可供免费使用的图片
  • Pexels 精美的免费图片和视频
  • Burst 免费高分辨率图片,可用于网站和商业用途
  • ISO Republic 使用 CC0 许可的免费高分辨率图片和视频
  • Pixabay 令人惊叹的免费(公共领域)图片和视频站点
  • StockSnap.io 精美的免费图片,同样使用 CC0 许可
  • Photopea 在线图片编辑工具,支持大量高级功能
  • Online Image Compressor 在线图片压缩工具,一次可以压缩多达 20 张图片
  • Bulk Resize Photos 最快的在线图片缩放工具(图片缩放和压缩在本地完成,无需上传到服务器)

参考

可访问性

部署

  • GitHub Pages GitHub 提供的免费静态网站托管服务
  • Netlify 30 秒内部署你的网站
  • Vercel 快速部署你的网站
  • Surge 只需一个命令就可以发布你的网站
  • Heroku 在云端构建、运行你的应用

其他

查看原文

赞 69 收藏 60 评论 7

dragon 收藏了文章 · 9月9日

糟糕,在错误的分支开发了新功能,该怎么处理呢?

image

最近在开发项目的一个小需求的时候,发生了一件尴尬的事情。那就是当我把新功能开发完成的时候,忽然发现自己开发使用的分支是错误的分支。不过我记得之前学习git的时候有一个git stash的命令可以把当前没有提交的内容存档起来,然后可以在切换分支之后把当前的存档应用到目标分支。不过因为平时不怎么使用这个命令,所以有点生疏了,需要再次去看看文档。

花了十几分钟,把git stash相关的命令又再次温习了一下,接着就顺利地把这个问题给解决掉。因为平时的开发也都是遵循相关的git流程,一般不会出现什么错误,而且平时使用的git命令也都是一些常用的。这次出现这个问题有一部分原因是因为这个项目不是一个长期维护的项目,当开发新功能的时候,一打开项目,就以为还在自己的开发分支。也没及时检查一下开发的分支是否正确。更深层次的原因还是因为git掌握得不够好。也正好借这个机会,把相关的命令再次好好复习一下,也挺好的

其实当你在错误的分支开发了新功能之后,这里会有三种情况:

  • 新功能还没有在本地进行commit(提交),也就是我这次遇到的情况
  • 新功能已经在本地提交了,但是还没有push到远程仓库
  • 新功能已经在本地提交了,且push到了远程仓库

虽然我遇到的是第一种情况,那么当我解决这个问题之后,我很自然的就会想:如果遇到了另外两种情况我该怎么处理呢?这篇文章就跟大家一起探讨一下针对上述三种情况下,如果你在错误的分支开发了新功能,我们应该怎么做。

新功能还没有在本地进行commit(提交)

在这种情况下我们可以在当前分支下使用:

git stash

这个命令表示把我们当前修改的内容暂存起来,然后我们的工作区就恢复到在没有开发新功能之前的样子。

这个时候我们需要切换到正确的工作分支,然后运行命令:

git stash apply

这个命令表示把我们之前暂存的内容,应用到当前分支。这样我们就相当于把修改的内容从一个分支移动到了另一个分支,是不是很简单呢。

上面那两个命令也是我解决这个问题中使用的命令。我觉得不能满足于只解决这个问题,我需要详细的了解一下有关git stash的命令,接下来的内容是关于git stash的一些深入的内容,我们不仅要知其然,还要知其所以然。

首先我们需要知道使用git stash命令会把我们工作区和暂存区的修改保存下来,然后将这些修改的内容从当前的文件中移出并保存在存档库里面。所以我们就回到了之前没有修改过内容的干净的工作区。

git stash在没有添加任何参数的时候相当于git stash push命令,我们使用git stash创建一个当前修改的快照的时候,命令运行完会给出如下的信息:

Saved working directory and index state WIP on <branchname>: <hash> <commit message>

其中branchname是你当前所在分支的名字,hash是当前分支最近一次提交的hash值,commit message就是你最近的一次提交的时候添加的提交信息。

对于当前只想存储一个快照的情况下使用git stash是比较方便直观的,如果你在当前分支想存储多个快照,那么最好给每一个快照添加一些解释信息,以便使用的时候能够知道每一个快照都是干嘛的。

我们可以使用git stash push -m message来给每一个快照添加详细的说明信息,比如:

git stash push -m “add feature 1”

在这个命令行运行完成之后,在终端上会显示如下的信息:

Saved working directory and index state On <branchname>: add feature 1

根据终端显示的信息,我们可以知道当前这个快照是在那个分支产生的,并且有了add feature 1这个详细的描述,等到以后使用的时候会更加的清楚一点。

当我们有了很多快照的时候,我们可能想看一下当前的快照列表。这个时候我们可以使用git stash list来看一下当前的快照列表。在终端运行git stash list后,如果你在之前添加了一些快照的话,会显示如下的一些信息:

stash@{0}: On <branchname>: add feature 1
stash@{1}: On <branchname>: add feature 0
stash@{2}: On <branchname>: <message>
stash@{3}: WIP on <branchname>: 47e52ae <commit message>
stash@{4}: On <branchname>: <message>

从上面的信息中我们可以知道最新的快照是排在最上面的,存储快照的是一个栈,所以最新添加的快照是放在最上面的。

如果我们想查看最近一次快照跟生成快照当时已提交的文件之间的变化情况的话,可以使用命令git stash show。这个命令默认展示的是文件的差别统计。如果想展示具体改动的内容的话,可以使用git stash show -p

因为我们有不止一个快照,所以我们还想要看之前的快照跟产生这个快照当时已提交的版本之间的差异的话,我们可以在上面的命令后面添加快照的索引,比如如果你想看上面add feature 0这个快照的文件变动的话,可以使用下面的命令:

git stash show stash@{1} # 简略的信息
git stash show -p stash@{1} # 详细的内容更改

接下来就到了应用(恢复)快照的时候了,如果这时候你想把某个快照的内容应用于当前的分支的话,只需要运行命令:

git stash apply # 将最新的快照内容应用于当前分支
git stash apply stash@{n} # n表示具体的快照索引

这样就可以把之前保留的快照内容应用到当前的版本中了,在应用快照的过程中可能会产生冲突,这时候需要手动把冲突的内容处理一下,然后再次提交就可以了。

git stash apply可以添加--index参数,这个参数的作用是在应用快照的时候,会把之前已经添加到暂存区(索引区)的更改依旧保存在暂存区,如果不添加这个参数的话,所有的变更都会变成在工作区的变更(也就是没有保存在索引区的状态)。

我们可以测试一下,对一个文件进行更改,然后把更改添加(使用git add)到暂存区,然后再次添加一个更改,这次不添加到暂存区。我们运行git status命令会看到如下的内容:

On branch dev
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   20200830/index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   20200830/README.md

当我们运行git stash命令,然后运行git stash apply命令之后,会看到如下信息:

On branch dev
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   20200830/README.md
        modified:   20200830/index.html

no changes added to commit (use "git add" and/or "git commit -a")

所以当不使用--index参数的时候,不会保存之前在暂存区的状态。

关于git stash还有一些其它的命令,比如:

  • git stash drop:丢弃一个快照
  • git stash pop:应用最新的快照到当前分支,如果应用成功的话就把这个快照从存储快照的栈中移除
  • git stash clear:清除所有的快照

关于git stash一些常用的命令和操作上面已经讲解的差不多啦,如果大家想继续了解更多的话,可以参考git-stash

上面的内容主要是在我们新开发的功能还没有提交的情况下所做的一些处理,当我们开发的新功能已经在本地提交了的情况下,我们该如何处理呢?接下来我们就来探讨一下这个问题。

新功能已经在本地提交了,但是还没有push到远程仓库

如果新开发的功能已经在本地提交了,但是我们开发的这个分支是一个错误的分支。这个时候根据情况的不同,可以有两种处理的方式。

新的功能需要添加在一个新的分支

首先我们需要知道在我们添加新功能之前,当前分支处于哪一个提交。可以运行命令:

git log --oneline

查看当前分支的提交,可以看到有以下内容的输出:

085095f (HEAD -> master) update 5
47e52ae update 3
14fefac update 2
fd01444 add README.md
3c76ad1 init

找到我们添加新功能时,当前分支所处的提交。假如是fd01444,那么我们接下来要做的操作就是将HEAD指针指向fd01444,也就是把我们当前分支已提交的内容重置到我们开发新功能之前的样子。我们需要运行下面的命令:

git reset fd01444 # fd01444是某次提交的hash值

如果没有指明重置的模式的话,默认会使用--mixed模式,这样的话我们在fd01444这次提交之后的所有提交都会被重置为没有提交的状态。接下来我们需要把这些新开发的功能迁移到一个新的分支。这时候我们可以使用下面的命令进行操作:

git checkout -b <newbranch>

这样我们就创建了一个新的分支,并且把新添加的功能也都迁移了过去,接下来就是常规的添加和提交操作了。

新功能需要添加在另一个分支上

如果我们需要把当前添加的新功能迁移到另一个已经存在的分支,那么我们需要做的前几个步骤跟上面的操作是一样的:

git log --oneline # 查找新功能开发之前的提交
git reset <commit hash> # 将当前分支重置到新功能开发之前的提交

接下来我们现在的状态就回到了新功能还没有提交的状态,那么就可以继续使用git stash相关的命令去操作了。

我们还有另外一个方法也能够将已提交到当前分支的功能添加到另一个分支上,那就是使用git cherry-pick命令。首先我们还是先用git log --oneline查找当前已提交的功能的hash值,然后切换到目标分支,运行命令:

git cherry-pick <commit hash>

这样就把我们在另一个分支开发的功能,添加到我们想要的分支了。如果有冲突的话,需要手动处理一下冲突。然后我们回到最初的分支,再次运行git reset <commit hash>命令,把已提交的内容进行重置,然后运行命令:

git checkout -- .

把当前分支没有添加到暂存区的内容都清除掉,这样也可以达到我们上面所说的,把新功能添加到另一个分支的目的。

新功能已经在本地提交了,且push到了远程仓库

第三种情况就是,我们已经把新开发的功能push到远程的仓库了,但是我们忽然发现新功能不应该在这个分支开发,我们这个时候应该怎么办呢?

首先我们应该保持当前的工作区是没有修改的,是一个干净的状态。不然使用撤销命令的时候会提示你需要把当前的文件内容变更先提交或者生成快照。当我们的工作区的状态是干净的时候,我们就可以进行撤销操作了。

首先需要知道我们应该撤销那一次提交的状态。使用git log --oneline查看要撤销的提交的索引,然后运行下面的命令:

git revert <commit>

这个时候命令运行的终端会进入编辑器模式,让你填写提交的信息。当然你也可以使用参数--no-edit这样就不会在进行撤销操作的时候打开编辑模式了。

如果需要撤销的提交比较多的话,我们可以使用..表示一个提交记录的范围。比如c1..c2就表示c2的可达提交,且排除c1的可达提交。所谓可达的提交指的是:提交本身及其祖先链中提交的集合

我们可以举个例子:

... a - b - c - d - HEAD

如果上面表示的是某个分支的提交记录,那么对于b..d表示的就是c d这两个提交,对于a..d表示的就是b c d这三个提交。如果大家想了解更多相关的内容,可以在git-rev-list这里深入的学习一下。

所以我们如果想快速的撤销一段范围的提交的话,可以运行类似下面这样的命令:

git revert 54dc134..a72d612 --no-edit

上述命令的54dc134就表示c1a72d612就表示c2--no-edit表明我们在运行撤销操作的时候不打开编辑模式。

我们如果需要对远程的分支进行撤销的话,首先考虑的就是使用git revert命令,因为git revert命令不会修改历史的提交记录,只是在原来的提交基础上添加新的提交,所以不会造成代码的丢失。在多人合作的情况下使用git revert命令撤销push到远程的操作还是很有必要的。

如果大家对于上面的这些问题有更好的解决方案的话,欢迎大家在文章下面留言,我们可以一起探讨一下,一起进步。如果你对文章有什么意见和建议的话也欢迎在文章下面留言,或者在这里提出来,我会持续努力改进的。也欢迎大家关注我的公众号关山不难越,及时获取最新的文章更新。

参考链接:

查看原文

dragon 赞了文章 · 9月9日

糟糕,在错误的分支开发了新功能,该怎么处理呢?

image

最近在开发项目的一个小需求的时候,发生了一件尴尬的事情。那就是当我把新功能开发完成的时候,忽然发现自己开发使用的分支是错误的分支。不过我记得之前学习git的时候有一个git stash的命令可以把当前没有提交的内容存档起来,然后可以在切换分支之后把当前的存档应用到目标分支。不过因为平时不怎么使用这个命令,所以有点生疏了,需要再次去看看文档。

花了十几分钟,把git stash相关的命令又再次温习了一下,接着就顺利地把这个问题给解决掉。因为平时的开发也都是遵循相关的git流程,一般不会出现什么错误,而且平时使用的git命令也都是一些常用的。这次出现这个问题有一部分原因是因为这个项目不是一个长期维护的项目,当开发新功能的时候,一打开项目,就以为还在自己的开发分支。也没及时检查一下开发的分支是否正确。更深层次的原因还是因为git掌握得不够好。也正好借这个机会,把相关的命令再次好好复习一下,也挺好的

其实当你在错误的分支开发了新功能之后,这里会有三种情况:

  • 新功能还没有在本地进行commit(提交),也就是我这次遇到的情况
  • 新功能已经在本地提交了,但是还没有push到远程仓库
  • 新功能已经在本地提交了,且push到了远程仓库

虽然我遇到的是第一种情况,那么当我解决这个问题之后,我很自然的就会想:如果遇到了另外两种情况我该怎么处理呢?这篇文章就跟大家一起探讨一下针对上述三种情况下,如果你在错误的分支开发了新功能,我们应该怎么做。

新功能还没有在本地进行commit(提交)

在这种情况下我们可以在当前分支下使用:

git stash

这个命令表示把我们当前修改的内容暂存起来,然后我们的工作区就恢复到在没有开发新功能之前的样子。

这个时候我们需要切换到正确的工作分支,然后运行命令:

git stash apply

这个命令表示把我们之前暂存的内容,应用到当前分支。这样我们就相当于把修改的内容从一个分支移动到了另一个分支,是不是很简单呢。

上面那两个命令也是我解决这个问题中使用的命令。我觉得不能满足于只解决这个问题,我需要详细的了解一下有关git stash的命令,接下来的内容是关于git stash的一些深入的内容,我们不仅要知其然,还要知其所以然。

首先我们需要知道使用git stash命令会把我们工作区和暂存区的修改保存下来,然后将这些修改的内容从当前的文件中移出并保存在存档库里面。所以我们就回到了之前没有修改过内容的干净的工作区。

git stash在没有添加任何参数的时候相当于git stash push命令,我们使用git stash创建一个当前修改的快照的时候,命令运行完会给出如下的信息:

Saved working directory and index state WIP on <branchname>: <hash> <commit message>

其中branchname是你当前所在分支的名字,hash是当前分支最近一次提交的hash值,commit message就是你最近的一次提交的时候添加的提交信息。

对于当前只想存储一个快照的情况下使用git stash是比较方便直观的,如果你在当前分支想存储多个快照,那么最好给每一个快照添加一些解释信息,以便使用的时候能够知道每一个快照都是干嘛的。

我们可以使用git stash push -m message来给每一个快照添加详细的说明信息,比如:

git stash push -m “add feature 1”

在这个命令行运行完成之后,在终端上会显示如下的信息:

Saved working directory and index state On <branchname>: add feature 1

根据终端显示的信息,我们可以知道当前这个快照是在那个分支产生的,并且有了add feature 1这个详细的描述,等到以后使用的时候会更加的清楚一点。

当我们有了很多快照的时候,我们可能想看一下当前的快照列表。这个时候我们可以使用git stash list来看一下当前的快照列表。在终端运行git stash list后,如果你在之前添加了一些快照的话,会显示如下的一些信息:

stash@{0}: On <branchname>: add feature 1
stash@{1}: On <branchname>: add feature 0
stash@{2}: On <branchname>: <message>
stash@{3}: WIP on <branchname>: 47e52ae <commit message>
stash@{4}: On <branchname>: <message>

从上面的信息中我们可以知道最新的快照是排在最上面的,存储快照的是一个栈,所以最新添加的快照是放在最上面的。

如果我们想查看最近一次快照跟生成快照当时已提交的文件之间的变化情况的话,可以使用命令git stash show。这个命令默认展示的是文件的差别统计。如果想展示具体改动的内容的话,可以使用git stash show -p

因为我们有不止一个快照,所以我们还想要看之前的快照跟产生这个快照当时已提交的版本之间的差异的话,我们可以在上面的命令后面添加快照的索引,比如如果你想看上面add feature 0这个快照的文件变动的话,可以使用下面的命令:

git stash show stash@{1} # 简略的信息
git stash show -p stash@{1} # 详细的内容更改

接下来就到了应用(恢复)快照的时候了,如果这时候你想把某个快照的内容应用于当前的分支的话,只需要运行命令:

git stash apply # 将最新的快照内容应用于当前分支
git stash apply stash@{n} # n表示具体的快照索引

这样就可以把之前保留的快照内容应用到当前的版本中了,在应用快照的过程中可能会产生冲突,这时候需要手动把冲突的内容处理一下,然后再次提交就可以了。

git stash apply可以添加--index参数,这个参数的作用是在应用快照的时候,会把之前已经添加到暂存区(索引区)的更改依旧保存在暂存区,如果不添加这个参数的话,所有的变更都会变成在工作区的变更(也就是没有保存在索引区的状态)。

我们可以测试一下,对一个文件进行更改,然后把更改添加(使用git add)到暂存区,然后再次添加一个更改,这次不添加到暂存区。我们运行git status命令会看到如下的内容:

On branch dev
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   20200830/index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   20200830/README.md

当我们运行git stash命令,然后运行git stash apply命令之后,会看到如下信息:

On branch dev
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   20200830/README.md
        modified:   20200830/index.html

no changes added to commit (use "git add" and/or "git commit -a")

所以当不使用--index参数的时候,不会保存之前在暂存区的状态。

关于git stash还有一些其它的命令,比如:

  • git stash drop:丢弃一个快照
  • git stash pop:应用最新的快照到当前分支,如果应用成功的话就把这个快照从存储快照的栈中移除
  • git stash clear:清除所有的快照

关于git stash一些常用的命令和操作上面已经讲解的差不多啦,如果大家想继续了解更多的话,可以参考git-stash

上面的内容主要是在我们新开发的功能还没有提交的情况下所做的一些处理,当我们开发的新功能已经在本地提交了的情况下,我们该如何处理呢?接下来我们就来探讨一下这个问题。

新功能已经在本地提交了,但是还没有push到远程仓库

如果新开发的功能已经在本地提交了,但是我们开发的这个分支是一个错误的分支。这个时候根据情况的不同,可以有两种处理的方式。

新的功能需要添加在一个新的分支

首先我们需要知道在我们添加新功能之前,当前分支处于哪一个提交。可以运行命令:

git log --oneline

查看当前分支的提交,可以看到有以下内容的输出:

085095f (HEAD -> master) update 5
47e52ae update 3
14fefac update 2
fd01444 add README.md
3c76ad1 init

找到我们添加新功能时,当前分支所处的提交。假如是fd01444,那么我们接下来要做的操作就是将HEAD指针指向fd01444,也就是把我们当前分支已提交的内容重置到我们开发新功能之前的样子。我们需要运行下面的命令:

git reset fd01444 # fd01444是某次提交的hash值

如果没有指明重置的模式的话,默认会使用--mixed模式,这样的话我们在fd01444这次提交之后的所有提交都会被重置为没有提交的状态。接下来我们需要把这些新开发的功能迁移到一个新的分支。这时候我们可以使用下面的命令进行操作:

git checkout -b <newbranch>

这样我们就创建了一个新的分支,并且把新添加的功能也都迁移了过去,接下来就是常规的添加和提交操作了。

新功能需要添加在另一个分支上

如果我们需要把当前添加的新功能迁移到另一个已经存在的分支,那么我们需要做的前几个步骤跟上面的操作是一样的:

git log --oneline # 查找新功能开发之前的提交
git reset <commit hash> # 将当前分支重置到新功能开发之前的提交

接下来我们现在的状态就回到了新功能还没有提交的状态,那么就可以继续使用git stash相关的命令去操作了。

我们还有另外一个方法也能够将已提交到当前分支的功能添加到另一个分支上,那就是使用git cherry-pick命令。首先我们还是先用git log --oneline查找当前已提交的功能的hash值,然后切换到目标分支,运行命令:

git cherry-pick <commit hash>

这样就把我们在另一个分支开发的功能,添加到我们想要的分支了。如果有冲突的话,需要手动处理一下冲突。然后我们回到最初的分支,再次运行git reset <commit hash>命令,把已提交的内容进行重置,然后运行命令:

git checkout -- .

把当前分支没有添加到暂存区的内容都清除掉,这样也可以达到我们上面所说的,把新功能添加到另一个分支的目的。

新功能已经在本地提交了,且push到了远程仓库

第三种情况就是,我们已经把新开发的功能push到远程的仓库了,但是我们忽然发现新功能不应该在这个分支开发,我们这个时候应该怎么办呢?

首先我们应该保持当前的工作区是没有修改的,是一个干净的状态。不然使用撤销命令的时候会提示你需要把当前的文件内容变更先提交或者生成快照。当我们的工作区的状态是干净的时候,我们就可以进行撤销操作了。

首先需要知道我们应该撤销那一次提交的状态。使用git log --oneline查看要撤销的提交的索引,然后运行下面的命令:

git revert <commit>

这个时候命令运行的终端会进入编辑器模式,让你填写提交的信息。当然你也可以使用参数--no-edit这样就不会在进行撤销操作的时候打开编辑模式了。

如果需要撤销的提交比较多的话,我们可以使用..表示一个提交记录的范围。比如c1..c2就表示c2的可达提交,且排除c1的可达提交。所谓可达的提交指的是:提交本身及其祖先链中提交的集合

我们可以举个例子:

... a - b - c - d - HEAD

如果上面表示的是某个分支的提交记录,那么对于b..d表示的就是c d这两个提交,对于a..d表示的就是b c d这三个提交。如果大家想了解更多相关的内容,可以在git-rev-list这里深入的学习一下。

所以我们如果想快速的撤销一段范围的提交的话,可以运行类似下面这样的命令:

git revert 54dc134..a72d612 --no-edit

上述命令的54dc134就表示c1a72d612就表示c2--no-edit表明我们在运行撤销操作的时候不打开编辑模式。

我们如果需要对远程的分支进行撤销的话,首先考虑的就是使用git revert命令,因为git revert命令不会修改历史的提交记录,只是在原来的提交基础上添加新的提交,所以不会造成代码的丢失。在多人合作的情况下使用git revert命令撤销push到远程的操作还是很有必要的。

如果大家对于上面的这些问题有更好的解决方案的话,欢迎大家在文章下面留言,我们可以一起探讨一下,一起进步。如果你对文章有什么意见和建议的话也欢迎在文章下面留言,或者在这里提出来,我会持续努力改进的。也欢迎大家关注我的公众号关山不难越,及时获取最新的文章更新。

参考链接:

查看原文

赞 36 收藏 22 评论 2

dragon 收藏了文章 · 8月13日

8 种用于前端性能分析工具

作者:Mahdhi Rezvi
译者:前端小智
来源:blog.bitsrc

点赞再看,微信搜索 【大迁世界】 关注这个没有大厂背景,但有着一股向上积极心态人。本文 GitHubhttps://github.com/qq44924588... 上已经收录,文章的已分类,也整理了很多我的文档,和教程资料。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

我们可以编写一些漂亮,且吸引人的网站,但如果该网站无法快速加载到浏览器中,人们往往会跳过它。 尽管有许多性能规则,但归根结底,这全都取决于加载时间。

根据 Jakob Nielson说法,在网建的网站时,需要注意以下几点:

  • 小于100毫秒加载速度才是爽的
  • 100ms到300ms 感觉良好
  • 一秒钟大概是用户思路不被打断的极限。用户会感觉到延迟,但还可以接受
  • 47%的用户希望网页能在两秒或更短的时间内加载
  • 40% 的用户如果网页加载超过 3 秒,表示会放弃该网站
  • 10秒左右是用户注意力的极限。 大多数用户会在10秒后离开你的网站

如上所述,即使在最差的网络带宽上,也需要确保页面尽快加载。 但这个说起来容易做起来难。

为了能帮助更好的实现这一目标,这里推荐了几个性能分析工具。

1. PageSpeed Insights

这是一个免费的服务,分析网页的内容,然后提出建议,使该网页更快。它为您提供了关键指标,如第一个内容绘制,总阻塞时间和更多。度量标准被分类为Field DataOrigin Summary,Lab Data,OpportunitiesDiagnosticsPassed Audits。它还为我们提供了进一步改进的建议。

clipboard.png

2. Lighthouse

Lighthouse 是一个开源的自动化工具,用于改进网络应用的质量。 你可以将其作为一个 Chrome 扩展程序运行,或从命令行运行。 你为 Lighthouse 提供一个您要审查的网址,它将针对此页面运行一连串的测试,然后生成一个有关页面性能的报告。

从此处,您可以失败的测试为指示器,看看可以采取哪些措施来改进您的应用。

注意: Lighthouse 目前非常关注 Progressive Web App (PWA) 功能,如“添加到主屏幕”和离线支持。不过,此项目的首要目标是针对网络应用质量的各个方面提供端到端审查。

运行 Lighthouse 的方式有两种:作为 Chrome 扩展程序运行,或作为命令行工具运行。 Chrome 扩展程序提供了一个对用户更友好的界面,方便读取报告。 命令行工具允许您将 Lighthouse 集成到持续集成系统。

clipboard.png

3. WebPageTest

WebPageTest是一个在线的免费性能评测网站,支持IE,Chrome,使用真正的浏览器(IE和Chrome)和真实的消费者连接速度,从全球多个地点运行免费网站速度测试。可以运行简单的测试或执行高级测试,包括多步骤事务、视频捕获、内容阻塞等等。还将依据测试结果提供丰富的诊断信息,包括资源加载瀑布图,页面速度优化检查和改进建议,会给每一项内容一个最终的评级。

WebpageTest 主要提供了Advanced Testing、simple Testing、Visual Comparison、Traceroute四个功能,我们主要关注Advanced Testing。

如何使用WebPageTest

  • 填写需要测试的URL
  • 填写Test Location,下拉选择即可,可选移动端设备(包括Android、IOS),可选PC端(分地区,每个地区可支持的浏览器不同)
  • 可选支持的浏览器
  • 点击右侧START TEST

clipboard.png

4. Pingdom

我最喜欢的功能是分析后的的摘要,其中会为我们提供有关网站内容和请求的摘要。 我发现这对于了解网页上提供的内容有很大帮助。

clipboard.png

5. Sitespeed.io

Sitespeed.io 是一款开源的Web性能测试工具,用来衡量Web网站的综合性能,帮助开发和测试人员分析网页的加载速度和渲染性能。

Sitespeed.io通过驱动浏览器(如:Chrome、Firefox)进行测试,然后从开发者的站点收集多个页面的数据,并根据最佳实践等规则来分析这些网页,然后将结果以HTML报告的形式输出。

Sitespeed.io 满足了一个完整的Web性能测试工具所需的3个关键功能:

  1. 使用真实的浏览器测试Web站点,模拟真实的用户进行请求连接,收集以用户为中心的重要指标,如:响应速度指标、第一视觉呈现
  2. 可分析页面的组成,并给出相应性能反馈,增加终端用户的使用体验友好性
  3. 通过收集和保存页面组成的数据,便于跟踪定位

clipboard.png

6. Calibre

Caliber 是一款多功能的性能监控套件,可帮助你监控和审核网站的性能。 它还允许你通过指定测试服务器的位置,管理模拟的广告首选项甚至模拟移动设备来模拟现实条件。 它还允许你设置预算,并通过为你提供性能下降来帮助你将预算保持在预算之内。

clipboard.png

7. SpeedCurve

SpeedCurve 既可以让你追踪竞争对手的性能表现,也可以追踪自己的性能表现。

使用 SpeedCurve 时,你可以查看某个因素在不同站点的速度表现。对于移动用户来说,他们希望网站在手机上加载起来要快于电脑,如果感到加载迟缓,往往会迅速关上网页,所以,网站的响应速度对他们很重要。

SpeedCurve 还提供了综合监控。综合监控是在受控环境中模拟你的网站。你可以自定义选项,比如网络速度、设备、操作系统等等。

clipboard.png

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

8. SpeedTracker

SpeedTracker是一个运行在WebPageTest之上的工具,可在你的网站上进行定期的性能测试,并直观显示各种性能指标随时间变化的方式。 这使你可以不断评估网站,并查看新功能如何影响网站的性能。 你还可以定义预算并通过电子邮件和Slack获取警报。

clipboard.png

人才们的 【三连】 就是小智不断分享的最大动力,如果本篇博客有任何错误和建议,欢迎人才们留言,最后,谢谢大家的观看。


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://blog.bitsrc.io/perfor...

交流

文章每周持续更新,可以微信搜索 【大迁世界 】 第一时间阅读,回复 【福利】 有多份前端视频等着你,本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,欢迎Star。

查看原文

dragon 赞了文章 · 8月13日

8 种用于前端性能分析工具

作者:Mahdhi Rezvi
译者:前端小智
来源:blog.bitsrc

点赞再看,微信搜索 【大迁世界】 关注这个没有大厂背景,但有着一股向上积极心态人。本文 GitHubhttps://github.com/qq44924588... 上已经收录,文章的已分类,也整理了很多我的文档,和教程资料。

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

我们可以编写一些漂亮,且吸引人的网站,但如果该网站无法快速加载到浏览器中,人们往往会跳过它。 尽管有许多性能规则,但归根结底,这全都取决于加载时间。

根据 Jakob Nielson说法,在网建的网站时,需要注意以下几点:

  • 小于100毫秒加载速度才是爽的
  • 100ms到300ms 感觉良好
  • 一秒钟大概是用户思路不被打断的极限。用户会感觉到延迟,但还可以接受
  • 47%的用户希望网页能在两秒或更短的时间内加载
  • 40% 的用户如果网页加载超过 3 秒,表示会放弃该网站
  • 10秒左右是用户注意力的极限。 大多数用户会在10秒后离开你的网站

如上所述,即使在最差的网络带宽上,也需要确保页面尽快加载。 但这个说起来容易做起来难。

为了能帮助更好的实现这一目标,这里推荐了几个性能分析工具。

1. PageSpeed Insights

这是一个免费的服务,分析网页的内容,然后提出建议,使该网页更快。它为您提供了关键指标,如第一个内容绘制,总阻塞时间和更多。度量标准被分类为Field DataOrigin Summary,Lab Data,OpportunitiesDiagnosticsPassed Audits。它还为我们提供了进一步改进的建议。

clipboard.png

2. Lighthouse

Lighthouse 是一个开源的自动化工具,用于改进网络应用的质量。 你可以将其作为一个 Chrome 扩展程序运行,或从命令行运行。 你为 Lighthouse 提供一个您要审查的网址,它将针对此页面运行一连串的测试,然后生成一个有关页面性能的报告。

从此处,您可以失败的测试为指示器,看看可以采取哪些措施来改进您的应用。

注意: Lighthouse 目前非常关注 Progressive Web App (PWA) 功能,如“添加到主屏幕”和离线支持。不过,此项目的首要目标是针对网络应用质量的各个方面提供端到端审查。

运行 Lighthouse 的方式有两种:作为 Chrome 扩展程序运行,或作为命令行工具运行。 Chrome 扩展程序提供了一个对用户更友好的界面,方便读取报告。 命令行工具允许您将 Lighthouse 集成到持续集成系统。

clipboard.png

3. WebPageTest

WebPageTest是一个在线的免费性能评测网站,支持IE,Chrome,使用真正的浏览器(IE和Chrome)和真实的消费者连接速度,从全球多个地点运行免费网站速度测试。可以运行简单的测试或执行高级测试,包括多步骤事务、视频捕获、内容阻塞等等。还将依据测试结果提供丰富的诊断信息,包括资源加载瀑布图,页面速度优化检查和改进建议,会给每一项内容一个最终的评级。

WebpageTest 主要提供了Advanced Testing、simple Testing、Visual Comparison、Traceroute四个功能,我们主要关注Advanced Testing。

如何使用WebPageTest

  • 填写需要测试的URL
  • 填写Test Location,下拉选择即可,可选移动端设备(包括Android、IOS),可选PC端(分地区,每个地区可支持的浏览器不同)
  • 可选支持的浏览器
  • 点击右侧START TEST

clipboard.png

4. Pingdom

我最喜欢的功能是分析后的的摘要,其中会为我们提供有关网站内容和请求的摘要。 我发现这对于了解网页上提供的内容有很大帮助。

clipboard.png

5. Sitespeed.io

Sitespeed.io 是一款开源的Web性能测试工具,用来衡量Web网站的综合性能,帮助开发和测试人员分析网页的加载速度和渲染性能。

Sitespeed.io通过驱动浏览器(如:Chrome、Firefox)进行测试,然后从开发者的站点收集多个页面的数据,并根据最佳实践等规则来分析这些网页,然后将结果以HTML报告的形式输出。

Sitespeed.io 满足了一个完整的Web性能测试工具所需的3个关键功能:

  1. 使用真实的浏览器测试Web站点,模拟真实的用户进行请求连接,收集以用户为中心的重要指标,如:响应速度指标、第一视觉呈现
  2. 可分析页面的组成,并给出相应性能反馈,增加终端用户的使用体验友好性
  3. 通过收集和保存页面组成的数据,便于跟踪定位

clipboard.png

6. Calibre

Caliber 是一款多功能的性能监控套件,可帮助你监控和审核网站的性能。 它还允许你通过指定测试服务器的位置,管理模拟的广告首选项甚至模拟移动设备来模拟现实条件。 它还允许你设置预算,并通过为你提供性能下降来帮助你将预算保持在预算之内。

clipboard.png

7. SpeedCurve

SpeedCurve 既可以让你追踪竞争对手的性能表现,也可以追踪自己的性能表现。

使用 SpeedCurve 时,你可以查看某个因素在不同站点的速度表现。对于移动用户来说,他们希望网站在手机上加载起来要快于电脑,如果感到加载迟缓,往往会迅速关上网页,所以,网站的响应速度对他们很重要。

SpeedCurve 还提供了综合监控。综合监控是在受控环境中模拟你的网站。你可以自定义选项,比如网络速度、设备、操作系统等等。

clipboard.png

大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】

8. SpeedTracker

SpeedTracker是一个运行在WebPageTest之上的工具,可在你的网站上进行定期的性能测试,并直观显示各种性能指标随时间变化的方式。 这使你可以不断评估网站,并查看新功能如何影响网站的性能。 你还可以定义预算并通过电子邮件和Slack获取警报。

clipboard.png

人才们的 【三连】 就是小智不断分享的最大动力,如果本篇博客有任何错误和建议,欢迎人才们留言,最后,谢谢大家的观看。


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://blog.bitsrc.io/perfor...

交流

文章每周持续更新,可以微信搜索 【大迁世界 】 第一时间阅读,回复 【福利】 有多份前端视频等着你,本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,欢迎Star。

查看原文

赞 26 收藏 18 评论 0

dragon 收藏了文章 · 8月11日

Nginx 流控搞不好,背锅跑路少不了!


链接:https://www.cnblogs.com/zjfja...
作者:雪山上的蒲公

前几天,以前一个老同事在微信上和我吐槽,一次周未休息,突然收到公司服务器告警,有一台服务器挂掉了,导致影响一部分公司业务的运行,事后查看发现原来是前端Nginx流控配置的不够科学,不得不背上一锅,影响了这个月的KPI考核和当年中的加薪指标。

可见这Nginx流控的配置还是很重要,所以,本篇文章将会介绍Nginx的流量限制的基础知识和高级配置,”流量限制”在Nginx Plus中也适用。

流量限制(rate-limiting),是Nginx中一个非常实用,却经常被错误理解和错误配置的功能。我们可以用来限制用户在给定时间内HTTP请求的数量。请求,可以是一个简单网站首页的GET请求,也可以是登录表单的POST请求。

流量限制可以用作安全目的,比如可以减慢暴力密码破解的速率。通过将传入请求的速率限制为真实用户的典型值,并标识目标URL地址(通过日志),还可以用来抵御DDOS攻击。更常见的情况,该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。

Nginx如何限流

Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),该算法在通讯和分组交换计算机网络中广泛使用,用以处理带宽有限时的突发情况。就好比,一个桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水将会溢出;同样,在请求处理方面,水代表来自客户端的请求,水桶代表根据”先进先出调度算法”(FIFO)等待被处理的请求队列,桶底漏出的水代表离开缓冲区被服务器处理的请求,桶口溢出的水代表被丢弃和不被处理的请求。

配置基本的限流

“流量限制”配置两个主要的指令,limit_req_zone和limit_req,如下所示:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {   
location /login/ {     
limit_req zone=mylimit;  
proxy_pass http://my_upstream;  
}
}

limit_req_zone指令定义了流量限制相关的参数,而limit_req指令在出现的上下文中启用流量限制(示例中,对于”/login/”的所有请求)。limit_req_zone指令通常在HTTP块中定义,使其可在多个上下文中使用,它需要以下三个参数:

  • Key - 定义应用限制的请求特性。示例中的Nginx变量remote_addr,占用更少的空间)
  • Zone - 定义用于存储每个IP地址状态以及被限制请求URL访问频率的共享内存区域。保存在内存共享区域的信息,意味着可以在Nginx的worker进程之间共享。定义分为两个部分:通过zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000个IP地址的状态信息,大约需要1MB,所以示例中区域可以存储160000个IP地址。
  • Rate - 定义最大请求速率。在示例中,速率不能超过每秒10个请求。Nginx实际上以毫秒的粒度来跟踪请求,所以速率限制相当于每100毫秒1个请求。因为不允许”突发情况”(见下一章节),这意味着在前一个请求100毫秒内到达的请求将被拒绝。
当Nginx需要添加新条目时存储空间不足,将会删除旧条目。如果释放的空间仍不够容纳新记录,Nginx将会返回 503状态码(Service Temporarily Unavailable)。另外,为了防止内存被耗尽,Nginx每次创建新条目时,最多删除两条60秒内未使用的条目。

limit_req_zone指令设置流量限制和共享内存区域的参数,但实际上并不限制请求速率。所以需要通过添加limit_req指令,将流量限制应用在特定的location或者server块。在上面示例中,我们对/login/请求进行流量限制。

现在每个IP地址被限制为每秒只能请求10次/login/,更准确地说,在前一个请求的100毫秒内不能请求该URL。

处理突发

如果我们在100毫秒内接收到2个请求,怎么办?对于第二个请求,Nginx将给客户端返回状态码503。这可能并不是我们想要的结果,因为应用本质上趋向于突发性。相反地,我们希望缓冲任何超额的请求,然后及时地处理它们。我们更新下配置,在limit_req中使用burst参数:

location /login/ {   
limit_req zone=mylimit burst=20;    
proxy_pass http://my_upstream;
}

burst参数定义了超出zone指定速率的情况下(示例中的mylimit区域,速率限制在每秒10个请求,或每100毫秒一个请求),客户端还能发起多少请求。上一个请求100毫秒内到达的请求将会被放入队列,我们将队列大小设置为20。

这意味着,如果从一个给定IP地址发送21个请求,Nginx会立即将第一个请求发送到上游服务器群,然后将余下20个请求放在队列中。然后每100毫秒转发一个排队的请求,只有当传入请求使队列中排队的请求数超过20时,Nginx才会向客户端返回503。

无延迟的排队

配置burst参数将会使通讯更流畅,但是可能会不太实用,因为该配置会使站点看起来很慢。在上面的示例中,队列中的第20个包需要等待2秒才能被转发,此时返回给客户端的响应可能不再有用。要解决这个情况,可以在burst参数后添加nodelay参数:

location /login/ {   
limit_req zone=mylimit burst=20 nodelay;   
proxy_pass http://my_upstream;
}

使用nodelay参数,Nginx仍将根据burst参数分配队列中的位置,并应用已配置的速率限制,而不是清理队列中等待转发的请求。相反地,当一个请求到达“太早”时,只要在队列中能分配位置,Nginx将立即转发这个请求。将队列中的该位置标记为”taken”(占据),并且不会被释放以供另一个请求使用,直到一段时间后才会被释放(在这个示例中是,100毫秒后)。

假设如前所述,队列中有20个空位,从给定的IP地址发出的21个请求同时到达。Nginx会立即转发这个21个请求,并且标记队列中占据的20个位置,然后每100毫秒释放一个位置。如果是25个请求同时到达,Nginx将会立即转发其中的21个请求,标记队列中占据的20个位置,并且返回503状态码来拒绝剩下的4个请求。

现在假设,第一组请求被转发后101毫秒,另20个请求同时到达。队列中只会有一个位置被释放,所以Nginx转发一个请求并返回503状态码来拒绝其他19个请求。如果在20个新请求到达之前已经过去了501毫秒,5个位置被释放,所以Nginx立即转发5个请求并拒绝另外15个。

效果相当于每秒10个请求的“流量限制”。如果希望不限制两个请求间允许间隔的情况下实施“流量限制”,nodelay参数是很实用的。

注意:对于大部分部署,我们建议使用burst和nodelay参数来配置limit_req指令。

高级配置示例

通过将基本的“流量限制”与其他Nginx功能配合使用,我们可以实现更细粒度的流量限制。

白名单

下面这个例子将展示,如何对任何不在白名单内的请求强制执行“流量限制”:

geo $limit {  
default        1;  
10.0.0.0/8       0;   
192.168.0.0/64     0;
}
map $limit $limit_key {    0 "";   
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
server { 
location / {      
limit_req zone=req_zone burst=10 nodelay;     
# ...    
}
}

这个例子同时使用了geo和map指令。geo块将给在白名单中的IP地址对应的$limit变量分配一个值0,给其它不在白名单中的分配一个值1。然后我们使用一个映射将这些值转为key,如下:

  • 如果变量的值是,limit_key变量将被赋值为空字符串
  • 如果变量的值是,limit_key变量将被赋值为客户端二进制形式的IP地址 两个指令配合使用,白名单内IP地址的$limit_key变量被赋值为空字符串,不在白名单内的被赋值为客户端的IP地址。当limit_req_zone后的第一个参数是空字符串时,不会应用“流量限制”,所以白名单内的IP地址(10.0.0.0/8和192.168.0.0/24 网段内)不会被限制。其它所有IP地址都会被限制到每秒5个请求。

limit_req指令将限制应用到/的location块,允许在配置的限制上最多超过10个数据包的突发,并且不会延迟转发。

location包含多limit_req指令

我们可以在一个location块中配置多个limit_req指令。符合给定请求的所有限制都被应用时,意味着将采用最严格的那个限制。例如,多个指令都制定了延迟,将采用最长的那个延迟。同样,请求受部分指令影响被拒绝,即使其他指令允许通过也无济于事。

扩展前面将“流量限制”应用到白名单内IP地址的例子:

http {    
# ...    
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;   
limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;  
server {     
# ...      
location / {      
limit_req zone=req_zone burst=10 nodelay;          
limit_req zone=req_zone_wl burst=20 nodelay;         
# ...      
}    
}
}

白名单内的IP地址不会匹配到第一个“流量限制”,而是会匹配到第二个req_zone_wl,并且被限制到每秒15个请求。不在白名单内的IP地址两个限制能匹配到,所以应用限制更强的那个:每秒5个请求。

配置相关功能

日志记录 默认情况下,Nginx会在日志中记录由于流量限制而延迟或丢弃的请求,如下所示:

2015/06/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.1.2, server: nginx.com, <br>request: "GET / HTTP/1.0", host: "nginx.com"

日志条目中包含的字段:

  • limiting requests - 表明日志条目记录的是被“流量限制”请求
  • excess - 每毫秒超过对应“流量限制”配置的请求数量
  • zone - 定义实施“流量限制”的区域
  • client - 发起请求的客户端IP地址
  • server - 服务器IP地址或主机名
  • request - 客户端发起的实际HTTP请求
  • host - HTTP报头中host的值

默认情况下,Nginx以error级别来记录被拒绝的请求,如上面示例中的[error]所示(Ngin以较低级别记录延时请求,一般是info级别)。如要更改Nginx的日志记录级别,需要使用limit_req_log_level指令。这里,我们将被拒绝请求的日志记录级别设置为warn:

location /login/ {   
limit_req zone=mylimit burst=20 nodelay;   
limit_req_log_level warn; 
proxy_pass http://my_upstream;
}

发送到客户端的错误代码

一般情况下,客户端超过配置的流量限制时,Nginx响应状态码为503(Service Temporarily Unavailable)。可以使用limit_req_status指令来设置为其它状态码(例如下面的444状态码):

location /login/ {   
limit_req zone=mylimit burst=20 nodelay;  
limit_req_status 444;
}

指定location拒绝所有请求

如果你想拒绝某个指定URL地址的所有请求,而不是仅仅对其限速,只需要在location块中配置deny all指令:

location /foo.php { 
deny all;
}

总结

前文已经涵盖了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括为HTTP请求的不同loation设置请求速率,给“流量限制”配置burst和nodelay参数。还涵盖了针对客户端IP地址的白名单和黑名单应用不同“流量限制”的高级配置,阐述了如何去日志记录被拒绝和延时的请求。

image

查看原文

dragon 赞了文章 · 8月11日

Nginx 流控搞不好,背锅跑路少不了!


链接:https://www.cnblogs.com/zjfja...
作者:雪山上的蒲公

前几天,以前一个老同事在微信上和我吐槽,一次周未休息,突然收到公司服务器告警,有一台服务器挂掉了,导致影响一部分公司业务的运行,事后查看发现原来是前端Nginx流控配置的不够科学,不得不背上一锅,影响了这个月的KPI考核和当年中的加薪指标。

可见这Nginx流控的配置还是很重要,所以,本篇文章将会介绍Nginx的流量限制的基础知识和高级配置,”流量限制”在Nginx Plus中也适用。

流量限制(rate-limiting),是Nginx中一个非常实用,却经常被错误理解和错误配置的功能。我们可以用来限制用户在给定时间内HTTP请求的数量。请求,可以是一个简单网站首页的GET请求,也可以是登录表单的POST请求。

流量限制可以用作安全目的,比如可以减慢暴力密码破解的速率。通过将传入请求的速率限制为真实用户的典型值,并标识目标URL地址(通过日志),还可以用来抵御DDOS攻击。更常见的情况,该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。

Nginx如何限流

Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),该算法在通讯和分组交换计算机网络中广泛使用,用以处理带宽有限时的突发情况。就好比,一个桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水将会溢出;同样,在请求处理方面,水代表来自客户端的请求,水桶代表根据”先进先出调度算法”(FIFO)等待被处理的请求队列,桶底漏出的水代表离开缓冲区被服务器处理的请求,桶口溢出的水代表被丢弃和不被处理的请求。

配置基本的限流

“流量限制”配置两个主要的指令,limit_req_zone和limit_req,如下所示:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {   
location /login/ {     
limit_req zone=mylimit;  
proxy_pass http://my_upstream;  
}
}

limit_req_zone指令定义了流量限制相关的参数,而limit_req指令在出现的上下文中启用流量限制(示例中,对于”/login/”的所有请求)。limit_req_zone指令通常在HTTP块中定义,使其可在多个上下文中使用,它需要以下三个参数:

  • Key - 定义应用限制的请求特性。示例中的Nginx变量remote_addr,占用更少的空间)
  • Zone - 定义用于存储每个IP地址状态以及被限制请求URL访问频率的共享内存区域。保存在内存共享区域的信息,意味着可以在Nginx的worker进程之间共享。定义分为两个部分:通过zone=keyword标识区域的名字,以及冒号后面跟区域大小。16000个IP地址的状态信息,大约需要1MB,所以示例中区域可以存储160000个IP地址。
  • Rate - 定义最大请求速率。在示例中,速率不能超过每秒10个请求。Nginx实际上以毫秒的粒度来跟踪请求,所以速率限制相当于每100毫秒1个请求。因为不允许”突发情况”(见下一章节),这意味着在前一个请求100毫秒内到达的请求将被拒绝。
当Nginx需要添加新条目时存储空间不足,将会删除旧条目。如果释放的空间仍不够容纳新记录,Nginx将会返回 503状态码(Service Temporarily Unavailable)。另外,为了防止内存被耗尽,Nginx每次创建新条目时,最多删除两条60秒内未使用的条目。

limit_req_zone指令设置流量限制和共享内存区域的参数,但实际上并不限制请求速率。所以需要通过添加limit_req指令,将流量限制应用在特定的location或者server块。在上面示例中,我们对/login/请求进行流量限制。

现在每个IP地址被限制为每秒只能请求10次/login/,更准确地说,在前一个请求的100毫秒内不能请求该URL。

处理突发

如果我们在100毫秒内接收到2个请求,怎么办?对于第二个请求,Nginx将给客户端返回状态码503。这可能并不是我们想要的结果,因为应用本质上趋向于突发性。相反地,我们希望缓冲任何超额的请求,然后及时地处理它们。我们更新下配置,在limit_req中使用burst参数:

location /login/ {   
limit_req zone=mylimit burst=20;    
proxy_pass http://my_upstream;
}

burst参数定义了超出zone指定速率的情况下(示例中的mylimit区域,速率限制在每秒10个请求,或每100毫秒一个请求),客户端还能发起多少请求。上一个请求100毫秒内到达的请求将会被放入队列,我们将队列大小设置为20。

这意味着,如果从一个给定IP地址发送21个请求,Nginx会立即将第一个请求发送到上游服务器群,然后将余下20个请求放在队列中。然后每100毫秒转发一个排队的请求,只有当传入请求使队列中排队的请求数超过20时,Nginx才会向客户端返回503。

无延迟的排队

配置burst参数将会使通讯更流畅,但是可能会不太实用,因为该配置会使站点看起来很慢。在上面的示例中,队列中的第20个包需要等待2秒才能被转发,此时返回给客户端的响应可能不再有用。要解决这个情况,可以在burst参数后添加nodelay参数:

location /login/ {   
limit_req zone=mylimit burst=20 nodelay;   
proxy_pass http://my_upstream;
}

使用nodelay参数,Nginx仍将根据burst参数分配队列中的位置,并应用已配置的速率限制,而不是清理队列中等待转发的请求。相反地,当一个请求到达“太早”时,只要在队列中能分配位置,Nginx将立即转发这个请求。将队列中的该位置标记为”taken”(占据),并且不会被释放以供另一个请求使用,直到一段时间后才会被释放(在这个示例中是,100毫秒后)。

假设如前所述,队列中有20个空位,从给定的IP地址发出的21个请求同时到达。Nginx会立即转发这个21个请求,并且标记队列中占据的20个位置,然后每100毫秒释放一个位置。如果是25个请求同时到达,Nginx将会立即转发其中的21个请求,标记队列中占据的20个位置,并且返回503状态码来拒绝剩下的4个请求。

现在假设,第一组请求被转发后101毫秒,另20个请求同时到达。队列中只会有一个位置被释放,所以Nginx转发一个请求并返回503状态码来拒绝其他19个请求。如果在20个新请求到达之前已经过去了501毫秒,5个位置被释放,所以Nginx立即转发5个请求并拒绝另外15个。

效果相当于每秒10个请求的“流量限制”。如果希望不限制两个请求间允许间隔的情况下实施“流量限制”,nodelay参数是很实用的。

注意:对于大部分部署,我们建议使用burst和nodelay参数来配置limit_req指令。

高级配置示例

通过将基本的“流量限制”与其他Nginx功能配合使用,我们可以实现更细粒度的流量限制。

白名单

下面这个例子将展示,如何对任何不在白名单内的请求强制执行“流量限制”:

geo $limit {  
default        1;  
10.0.0.0/8       0;   
192.168.0.0/64     0;
}
map $limit $limit_key {    0 "";   
1 $binary_remote_addr;
}
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;
server { 
location / {      
limit_req zone=req_zone burst=10 nodelay;     
# ...    
}
}

这个例子同时使用了geo和map指令。geo块将给在白名单中的IP地址对应的$limit变量分配一个值0,给其它不在白名单中的分配一个值1。然后我们使用一个映射将这些值转为key,如下:

  • 如果变量的值是,limit_key变量将被赋值为空字符串
  • 如果变量的值是,limit_key变量将被赋值为客户端二进制形式的IP地址 两个指令配合使用,白名单内IP地址的$limit_key变量被赋值为空字符串,不在白名单内的被赋值为客户端的IP地址。当limit_req_zone后的第一个参数是空字符串时,不会应用“流量限制”,所以白名单内的IP地址(10.0.0.0/8和192.168.0.0/24 网段内)不会被限制。其它所有IP地址都会被限制到每秒5个请求。

limit_req指令将限制应用到/的location块,允许在配置的限制上最多超过10个数据包的突发,并且不会延迟转发。

location包含多limit_req指令

我们可以在一个location块中配置多个limit_req指令。符合给定请求的所有限制都被应用时,意味着将采用最严格的那个限制。例如,多个指令都制定了延迟,将采用最长的那个延迟。同样,请求受部分指令影响被拒绝,即使其他指令允许通过也无济于事。

扩展前面将“流量限制”应用到白名单内IP地址的例子:

http {    
# ...    
limit_req_zone $limit_key zone=req_zone:10m rate=5r/s;   
limit_req_zone $binary_remote_addr zone=req_zone_wl:10m rate=15r/s;  
server {     
# ...      
location / {      
limit_req zone=req_zone burst=10 nodelay;          
limit_req zone=req_zone_wl burst=20 nodelay;         
# ...      
}    
}
}

白名单内的IP地址不会匹配到第一个“流量限制”,而是会匹配到第二个req_zone_wl,并且被限制到每秒15个请求。不在白名单内的IP地址两个限制能匹配到,所以应用限制更强的那个:每秒5个请求。

配置相关功能

日志记录 默认情况下,Nginx会在日志中记录由于流量限制而延迟或丢弃的请求,如下所示:

2015/06/13 04:20:00 [error] 120315#0: *32086 limiting requests, excess: 1.000 by zone "mylimit", client: 192.168.1.2, server: nginx.com, <br>request: "GET / HTTP/1.0", host: "nginx.com"

日志条目中包含的字段:

  • limiting requests - 表明日志条目记录的是被“流量限制”请求
  • excess - 每毫秒超过对应“流量限制”配置的请求数量
  • zone - 定义实施“流量限制”的区域
  • client - 发起请求的客户端IP地址
  • server - 服务器IP地址或主机名
  • request - 客户端发起的实际HTTP请求
  • host - HTTP报头中host的值

默认情况下,Nginx以error级别来记录被拒绝的请求,如上面示例中的[error]所示(Ngin以较低级别记录延时请求,一般是info级别)。如要更改Nginx的日志记录级别,需要使用limit_req_log_level指令。这里,我们将被拒绝请求的日志记录级别设置为warn:

location /login/ {   
limit_req zone=mylimit burst=20 nodelay;   
limit_req_log_level warn; 
proxy_pass http://my_upstream;
}

发送到客户端的错误代码

一般情况下,客户端超过配置的流量限制时,Nginx响应状态码为503(Service Temporarily Unavailable)。可以使用limit_req_status指令来设置为其它状态码(例如下面的444状态码):

location /login/ {   
limit_req zone=mylimit burst=20 nodelay;  
limit_req_status 444;
}

指定location拒绝所有请求

如果你想拒绝某个指定URL地址的所有请求,而不是仅仅对其限速,只需要在location块中配置deny all指令:

location /foo.php { 
deny all;
}

总结

前文已经涵盖了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括为HTTP请求的不同loation设置请求速率,给“流量限制”配置burst和nodelay参数。还涵盖了针对客户端IP地址的白名单和黑名单应用不同“流量限制”的高级配置,阐述了如何去日志记录被拒绝和延时的请求。

image

查看原文

赞 26 收藏 18 评论 0

认证与成就

  • 获得 168 次点赞
  • 获得 4 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 4 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-05-08
个人主页被 880 人浏览