前端工程化相关

270 阅读6分钟

linux

打包

$ tar [-z|-j|-J] [cv] [-f 新建的 tar 文件] filename...  ==打包压缩
$ tar [-z|-j|-J] [tv] [-f 已有的 tar 文件]              ==查看
$ tar [-z|-j|-J] [xv] [-f 已有的 tar 文件] [-C 目录]    ==解压缩
-z :使用 zip;
-j :使用 bzip2;
-J :使用 xz;
-c :新建打包文件;
-t :查看打包文件里面有哪些文件;
-x :解打包或解压缩的功能;
-v :在压缩/解压缩的过程中,显示正在处理的文件名;
-f : filename:要处理的文件;
-C 目录 : 在特定目录解压缩。

常用命令

mkdir 目录名 创建目录
rmdir 目录名 删除目录
touch 文件名 创建文件
rm 文件名 删除文件
cp 拷贝文件
mv 移动文件
ls 当前目录的所有内容
pwd 当前工作目录的绝对路径
cd 切换目录
cd ~ / cd : 切换到root
cd.. 回到上一级目录
find 找到文件
gzip / gunzip 压缩 /解压

shell

指定 bash 解释器

脚本以#!/bin/bash开头

建立一个文本文件,以aa.sh结尾的或者不需要后缀都可以:

#!/bin/bash
NUM=10
printf "输出数字$NUM\n"
echo $NUM

脚本运行

直接运行是会报错误的,需要给权限:

chmod +x ./demo1   # 使每个人都有执行的权限
chmod +rx ./demo1  # 使每个人都有读和执行的权限
chmod u+rx ./demo1 # 仅仅使脚本文件拥有者有读和执行的权限
chmod u+x ./demo1  # 只有自己可以执行,其它人不能执行
chmod ug+x ./demo1 # 只有自己以及同一群可以执行,其它人不能执行 
chmod 555 ./demo1  # 使每个人都有读和执行的权限

当前目录下运行脚本

./aa
# 输出结果===>
输出数字10
10

bash执行

bash aa.sh 

sh执行

sh aa.sh 

常用语法

一篇文章让你彻底掌握 shell 语言

YAML

YAML 可读性高,易于理解,用来表达数据序列化的格式。它的语法和其他高级语言类似,还可以简单表达数组、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件。

yaml文件其实也是一种配置文件类型,后缀名是.yaml或.yml都可以

yaml语法规则

  • 使用缩进表示层级关系。
  • 缩进时不允许使用 Tab 键,只允许使用空格。
  • 缩进的空格数不重要,但同级元素必须左侧对齐。
  • 大小写敏感。

YAML 常用写法

YAML 语言教程

YAML 支持以下三种数据结构:

  • 对象:键值对的集合
  • 数组:一组按次序排列的值
  • 字面量:单个的、不可拆分的值

YAML 字面量写法

字面量是指单个的,不可拆分的值,例如:数字、字符串、布尔值、以及日期等。

在 YAML 中,使用“key:[空格]value 的形式表示一对键值对(空格不能省略)。 字面量直接写在键值对的“value 中即可,且默认情况下字符串是不需要使用单引号或双引号的。

name: bianchengbang

文本块

如果你想引入多行的文本块,可以使用|符号,注意在冒号:和 |符号之间要有空格。

person:
  name: |
    Hello Java!!
    I am fine!
    Thanks! GoodBye!

它和加双引号的效果一样,双引号能转义特殊字符:

person:
  name: "Hello Java!!\nI am fine!\nThanks! GoodBye!"

YAML 对象写法

在 YAML 中,对象可能包含多个属性,每一个属性都是一对键值对。

普通写法,使用缩进表示对象与属性的层级关系。

website:   name: bianchengbang  url: www.biancheng.net

行内写法:

website: {name: bianchengbang,url: www.biancheng.net}

YAML 数组写法

YAML 使用“-”表示数组中的元素,普通写法如下:

pets:  -dog  -cat  -pig

行内写法

pets: [dog,cat,pig]

YAML 组织结构

一个 YAML 文件可以由一个或多个文档组成,文档之间使用“--- 作为分隔符,且个文档相互独立,互不干扰。如果 YAML 文件只包含一个文档,则“--- 分隔符可以省略。

---
website:  
  name: bianchengbang  
  url: www.biancheng.net
---
website: {name: bianchengbang,url: www.biancheng.net}
pets:
  -dog
  -cat
  -pig
---
pets: [dog,cat,pig]
name: "zhangsan \n lisi"

Nginx

Nginx是一款面向性能设计的 HTTP 服务器,能反向代理 HTTPHTTPS 和邮件相关(SMTPPOP3IMAP)的协议链接。并且提供了负载均衡以及 HTTP 缓存。它的设计充分使用异步事件模型,削减上下文调度的开销,提高服务器并发能力。采用了模块化设计,提供了丰富模块的第三方模块。

配置结构

下面是一个nginx配置文件的基本结构:

image

events { 

}

http 
{
    server
    { 
        location path
        {
            ...
        }
        location path
        {
            ...
        }
     }

    server
    {
        ...
    }

}
  • main:nginx的全局配置,对全局生效。
  • events:配置影响nginx服务器或与用户的网络连接。
  • http:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
  • server:配置虚拟主机的相关参数,一个http中可以有多个server。
  • location:配置请求的路由,以及各种页面的处理情况。
  • upstream:配置后端服务器具体地址,负载均衡配置不可或缺的部分。

常用命令

查看Nginx版本号:./nginx -v
启动 Nginx:./nginx
停止 Nginx:./nginx -s stop 或者./nginx -s quit
重新加载配置文件:./nginx -s reload

内置变量

下面是nginx一些配置中常用的内置全局变量,你可以在配置的任何位置使用它们。

变量名功能
$host请求信息中的Host,如果请求中没有Host行,则等于设置的服务器名
$request_method客户端请求类型,如GETPOST
$remote_addr客户端的IP地址
$args请求中的参数
$content_length请求头中的Content-length字段
$http_user_agent客户端agent信息
$http_cookie客户端cookie信息
$remote_addr客户端的IP地址
$remote_port客户端的端口
$server_protocol请求使用的协议,如HTTP/1.0、·HTTP/1.1`
$server_addr服务器地址
$server_name服务器名称
$server_port服务器的端口号

nginx解决跨域的原理

例如:

  • 前端server的域名为:fe.server.com
  • 后端服务的域名为:dev.server.com

现在我在fe.server.comdev.server.com发起请求一定会出现跨域。

现在我们只需要启动一个nginx服务器,将server_name设置为fe.server.com,然后设置相应的location以拦截前端需要跨域的请求,最后将请求代理回dev.server.com。如下面的配置:

server {
        listen       80;
        server_name  fe.server.com;
        location / {
                proxy_pass dev.server.com;
        }
}

这样可以完美绕过浏览器的同源策略:fe.server.com访问nginxfe.server.com属于同源访问,而nginx对服务端转发的请求不会触发浏览器的同源策略。

请求过滤

根据状态码过滤

error_page 500 501 502 503 504 506 /50x.html;
    location = /50x.html {
        #将跟路径改编为存放html的路径。
        root /root/static/html;
    }

根据URL名称过滤,精准匹配URL,不匹配的URL全部重定向到主页。

location / {
    rewrite  ^.*$ /index.html  redirect;
}

根据请求类型过滤。

if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
        return 403;
    }

配置gzip

GZIP是规定的三种标准HTTP压缩格式之一。目前绝大多数的网站都在使用GZIP传输 HTMLCSSJavaScript 等资源文件。

对于文本文件,GZip 的效果非常明显,开启后传输所需流量大约会降至 1/4 ~ 1/3

并不是每个浏览器都支持gzip的,如何知道客户端是否支持gzip呢,请求头中的Accept-Encoding来标识对压缩的支持。

image

启用gzip同时需要客户端和服务端的支持,如果客户端支持gzip的解析,那么只要服务端能够返回gzip的文件就可以启用gzip了,我们可以通过nginx的配置来让服务端支持gzip。下面的responecontent-encoding:gzip,指服务端开启了gzip的压缩方式。

image

    gzip                    on;
    gzip_http_version       1.1;        
    gzip_comp_level         5;
    gzip_min_length         1000;
    gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml;

gzip

  • 开启或者关闭gzip模块
  • 默认值为off
  • 可配置为on / off

gzip_http_version

  • 启用 GZip 所需的HTTP 最低版本
  • 默认值为HTTP/1.1

这里为什么默认版本不是1.0呢?

HTTP 运行在TCP 连接之上,自然也有着跟TCP 一样的三次握手、慢启动等特性。

启用持久连接情况下,服务器发出响应后让TCP连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。

image

为了尽可能的提高 HTTP 性能,使用持久连接就显得尤为重要了。

HTTP/1.1默认支持TCP持久连接,HTTP/1.0 也可以通过显式指定 Connection: keep-alive 来启用持久连接。对于TCP持久连接上的HTTP 报文,客户端需要一种机制来准确判断结束位置,而在 HTTP/1.0中,这种机制只有Content-Length。而在HTTP/1.1中新增的 Transfer-Encoding: chunked 所对应的分块传输机制可以完美解决这类问题。

nginx同样有着配置chunked的属性chunked_transfer_encoding,这个属性是默认开启的。

Nginx在启用了GZip的情况下,不会等文件 GZip 完成再返回响应,而是边压缩边响应,这样可以显著提高 TTFB(Time To First Byte,首字节时间,WEB 性能优化重要指标)。这样唯一的问题是,Nginx 开始返回响应时,它无法知道将要传输的文件最终有多大,也就是无法给出Content-Length这个响应头部。

所以,在HTTP1.0中如果利用Nginx启用了GZip,是无法获得Content-Length的,这导致HTTP1.0中开启持久链接和使用GZip只能二选一,所以在这里gzip_http_version默认设置为1.1

gzip_comp_level

  • 压缩级别,级别越高压缩率越大,当然压缩时间也就越长(传输快但比较消耗cpu)。
  • 默认值为 1
  • 压缩级别取值为1-9

gzip_min_length

  • 设置允许压缩的页面最小字节数,Content-Length小于该值的请求将不会被压缩
  • 默认值:0
  • 当设置的值较小时,压缩后的长度可能比原文件大,建议设置1000以上

gzip_types

  • 要采用gzip压缩的文件类型(MIME类型)
  • 默认值:text/html(默认不压缩js/css)

nginx如何实现负载均衡

Upstream指定后端服务器地址列表

upstream balanceServer {
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

在server中拦截响应请求,并将请求转发到Upstream中配置的服务器列表。

    server {
        server_name  fe.server.com;
        listen 80;
        location /api {
            proxy_pass http://balanceServer;
        }
    }

上面的配置只是指定了nginx需要转发的服务端列表,并没有指定分配策略。

nginx实现负载均衡的策略

image

轮询策略

默认情况下采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。

upstream balanceServer {
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

image

最小连接数策略

将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。

upstream balanceServer {
    least_conn;
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

image

最快响应时间策略

依赖于NGINX Plus,优先分配给响应时间最短的服务器。

upstream balanceServer {
    fair;
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

客户端ip绑定

来自同一个ip的请求永远只分配一台服务器,有效解决了动态网页存在的session共享问题。

upstream balanceServer {
    ip_hash;
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}

静态资源服务器

location ~* .(png|gif|jpg|jpeg)$ {
    root    /root/static/;  
    autoindex on;
    access_log  off;
    expires     10h;# 设置过期时间为10小时          
}

匹配以png|gif|jpg|jpeg为结尾的请求,并将请求转发到本地路径,root中指定的路径即nginx本地路径。同时也可以进行一些缓存的设置。

CI/CD 持续集成和持续交付

CI 指持续集成(Continuous Integration),CD 指持续交付(Continuous Delivery)和 持续部署(Continuous Deployment),是一种软件开发实践。意思是通过一系列自动化的脚本执行,实现开发过程中的代码的交付和部署,能够快速交付,提高团队开发的效率。

持续集成指的是频繁的将代码集成到主干环境,在保证高质量的同时,可以让产品快速迭代。持续交付是在持续集成之后,将软件的新版本交付给 QA 或者用户。在通过交付指标之后,自动部署到生产环境。

CI/CD 即可以仅指持续集成、持续交付构成的关联环节,也可以指持续集成、持续交付、持续部署构成的关联环节。在我们平时的开发中,这些概念都是表示是在代码开发完成后的自动化处理流程。

img

CI/CD 的具体流程如下:

  1. 在代码提交之后,CI 系统会自动通过 webhook 检测到代码变更,自动触发 CI 流程。
  2. 然后会进行静态代码检测,通常是进行一些快速的错误检查过程,比如语法检查,如果有错误就直接终止流程。
  3. 在进行完基础的代码检查之后,会进入自动构建环节,比如要进行代码效验、代码压缩、自动化测试等操作。
  4. 在构建完成之后,会进行一些回归测试、自动化测试、集成测试以及压力测试等。
  5. 在完成了必要的测试工作之后,就可以将代码部署到对应的环境中,在部署到生产环境之前,应该先部署在测试环境中再次验证。在部署到生产环境应使用对应的部署策略:蓝绿部署、灰度部署等。
  6. 在部署阶段,我们还要对项目的各个指标进行监控,出现异常及时做回滚操作。

Jenkins

Jenkins 是一款诞生比较早的老牌的开源 CI/CD 工具,可以自动化执行各种任务,包括构建、测试和部署软件。可以通过配置和编写脚本自动化执行 CI/CD 流程,代替手动 CD/CD 流程,从而节省开发时间,减少错误率,并且会将每一次构建结果记录下来。

Docker

在软件开发中,有一个老大难问题就是环境一致性。因为我们的软件是需要在计算机环境中运行,所以不同的环境可能会对软件运行的结果产生影响。

容器化部署就是将原先在部署服务器中执行的项目部署流程改为使用容器化的技术完成。容器化是一种新的部署思想和解决方案,是指把我们代码和我们需要的环境变量一起“打包”,放在一个隔离的空间内。因为容器是在一个隔离的空间内,所以可以不受环境或者其他因素的影响独立运行,可以做到环境隔绝。

Docker 将软件和其依赖一起打包在一个可移植的镜像中,在运行的时候会创建一个与外界隔离的容器,  我们将镜像存放在镜像仓库中。

就和 Docker 的 LOGO 一样,其思想就和集装箱的思想一样。我们在用轮船运货的时候,将不同的商品装在不同标准的集装箱中,各个集装箱之间就可以装不同的东西,互不影响。

Docker 中有三大重要概念:容器、镜像和仓库。镜像是 Docker 运行容器的前提,仓库是存放镜像的场所

容器

我们将软件打包成标准化单元,以用于开发、交付和部署,然后将其存放在容器中。我们可以通俗的理解为,容器就是存放东西的地方,存放的是软件运行所需要的代码、运行时环境、系统工具、设置等所有内容。

img

镜像

Docker 中的镜像是一个特殊的文件系统。提供容器运行时所需的代码、库、资源、配置文件和一些运行时的配置参数。镜像不包含任何的动态数据,为了能够使镜像最小化,通常会把配置参数,环境变量等信息在运行镜像时带入。比如服务启用时需要一份 DB 数据库链接信息,那我们在启用时会将这个信息通过 run命令带入到容器中,而不会写死在镜像之中。镜像内容在构建之后也不会改变。通过一个镜像可以创建多个容器实例。

镜像仓库

镜像仓库(Registry)是 Docker 集中存放镜像文件的地方,存储的镜像都以数据库(Blob)的方式存储在文件系统中。我们可以根据镜像仓库所处位置不同分为远端镜像仓库和本地镜像仓库。

一个 Docker Registry 中可以存放很多个镜像,当然在实际使用中我们会根据用途存放在不同的存储路径下。

Docker 的使用

当我们完成代码开发工作之后,该如何使用 Docker 来完成部署服务呢?使用 Docker 部署大致分为下图的流程:

img

首先我们需要有 Dockfile 文件,然后通过 Dockerfile 文件构建一个镜像,构建完的镜像需要在实际的机器上面运行,之后才能对外提供服务。