Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

NodeJS学习笔记

Node

PM2

node的一款进程管理工具

特性

  1. 内置负载均衡(使用 Node Cluster集群模块)
  2. 后台运行
  3. 0秒停机重载
  4. 具有Ubuntu和CentOS启动脚本
  5. 停止不稳定进程
  6. 控制台检测
  7. 提供HTTP API
  8. 远程控制和实时的接口API

基本命令

当Node接口分别定义在很多个文件中,此时我们想要启动所有接口,则可以使用:

1
2
npx pm2 start api.js
npx pm2 start api2.js

启动多个接口文件,一旦运行过start命令,服务就会一只启用

可以使用npx pm2 list

查看已经启动的服务

使用:

1
npx npm2 stop 0

即可停止某个服务,其中0代表服务在list中的id

使用

npx pm2 restart 0重启服务

npx pm2 delete 0将服务从list中删除

npx pm2 start api.js --watch用于监听文件的变得,自动重启服务

npx pm2 start api.js -i max用于监听文件的变得,自动重启服务,同时根据线程进行负载分配

npx pm2 start api.js --n aaa自定义服务的名称

npx pm2 monit查看服务运行状态(包含日志,堆占用等等信息)

Nginx

Nginx是一个高性能的HTTP和反向代理web服务器,同时提供IMAP/POP3/SMTP服务,支持5W个高并发。

前端主要使用Nginx搭建web服务器或进行反向代理解决跨域问题

底层由C语言编写

默认使用80端口

反向代理

正向代理

客户端由于某些原因无法访问一些服务器时,可以通过向代理服务器(VPN)发送请求,由代理服务器向目标站点发送请求后转发给客户端

img

反向代理

反向代理则是代理原本的服务器接收网络请求

他将请求转发给内部网络上的服务器,并将从服务器上得到的数据转发给客户端

通常会在具有服务器集群的项目中使用

img

负载均衡(upstream)

  • 轮询
    • Nginx默认的负载均衡方式
    • 请求按照时间顺序依次发给不同服务器
    • 掉线的服务器会被自动剔除
  • 权重
    • 指定每个服务的的权重比例
    • 权重和访问成正比
    • 适用于服务器性能不统一的集群

动静分离

一般而言前端项目都需要进行动静分离,静态资源(HTML,JS,CSS,img等)都部署在Ngnix服务器上,如果是静态资源则可以迅速从Nginx上获得资源,而动态资源则通过Nginx反向代理向服务器发送请求获得,从而提升效率

常用命令

  • nginx启动
  • nginx -s stop停止
  • nginx -s quit等待请求处理完成后停止
  • nginx -s reload重载ngnix配置文件
  • nginx -t检查ngnix配置文件是否包含语法错误(同时返回配置文件地址

配置文件

  • 全局块
    • user——指定可以运行ngnix服务的用户,用户组(windows上不生效
    • woker_process——指定ngnix进程数
    • pid——存放pid文件的目录
    • err_log logs/error.log——全局错误日志类型 debug info warn error存放地址
  • event块
    • accept_mutex——默认开启,开启后ngnix进程以串行处理请求,即一个请求只会唤醒一个经常。如果关闭会发生惊群效应,多个worker全部被唤醒但只有一个可以获取新连接
    • worker_connections单个进程最大连接数(=进程数+连接数)越大越好,但越大CPU占用越高
  • http块
    • include指令,用于引入其他的配置文件
    • default_type 如果Web程序没设置,Nginx也没对应文件的扩展名,就用Nginx 里默认的 default_type定义的处理方式。default_type application/octet-stream; #nginx默认文件类型
    • log_format指令,用于定义日志格式,此指令只能在http块中进行配置
    • sendfile 简单来说就是启用sendfile()系统调用来替换read()和write()调用,减少系统上下文切换从而提高性能,当 nginx 是静态文件服务器时,能极大提高nginx的性能表现
    • keepalive_timeout HTTP 有一个 KeepAlive 模式,它告诉 webserver 在处理完一个请求后保持这个 TCP 连接的打开状态。若接收到来自客户端的其它请求,服务端会利用这个未被关闭的连接,而不需要再建立一个连接。
    • gzip 开启Gzip压缩功能, 可以使网站的css、js 、xml、html 文件在传输时进行压缩,提高访问速度, 进而优化Nginx性能
    • server块
      • listen指令的配置非常灵活,可以单独制定ip,单独指定端口或者同时指定ip和端口
      • server_name nginx 允许一个虚拟主机有一个或多个名字,也可以使用通配符”*”来设置虚拟主机的名字 支持 ip 域名 通配符 正则等
      • location块
        • location 指令可以分为以下 3 类:
          • 前缀字符串匹配
            • 精确匹配 =
            • 前缀匹配 ^~(立刻停止后续的正则搜索)
            • 按文件中顺序的正则匹配 ~~*
            • 匹配不带任何修饰的前缀匹配。
          • 正则表达式匹配
          • 用于内部跳转的命名location
        • location root——root 指定目录的上级目录,并且该上级目录要含有locatoin指定名称的同名目录

反向代理

配置方法

反向代理中的常用配置字段:

1
2
proxy_pass
proxy_set_header

proxy_pass该指令用来设置被代理服务器地址,可以是主机名称、IP地址加端口号形式。

proxy_set_header该指令可以更改Nginx服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给代理的服务器

例如反向代理bilibili

1
2
3
4
5
location / {
root html;
index index.html index.htm;
proxy_pass http://bilibili.com;
}

反向代理解决跨域问题

利用反向代理的方法,借助Nginx向目标服务端发送请求来解决快于问题:

例如,我们有一个运行在9999端口上的服务端接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express')

const app = express()


app.get('/portal/list', (req, res) => {
res.json({
code: 200,
message: "搞咩啊"
})
})

app.listen(9000,()=>{
console.log('success');
})

此时由于我们前端页面部署在Nginx服务器上,默认地址为80,那么我们前端页面通过HTTPRequest向后端9999端口请求时,由于端口号不同,则直接访问会报跨域错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<html>
<body>
<a id="a"></a>
</body>
</html>
<script>
const a = document.getElementById("a")
a.onclick = () => {
let xhr = new XMLHttpRequest()

xhr.open('GET','/api/portal/list')

xhr.onreadystatechange = () => {
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
}

xhr.send(null)
}
</script>

配置新的location来让其根据特殊的PAI进行替换

1
2
3
4
5
6
7
8
location /api/ {
proxy_pass http://localhost:9000/; # 反向代理到目标服务器url
}
location / {
root html;
index index.html index.htm;
proxy_pass http://bilibili.com;
}

截取到/api/ 将会转发到 http://localhost:9000/

Vue histroy 模式 跳转路由404 问题

当我们把vue项目打包好放到nginx上并部署时,服务器是根据页面路由,去按路径寻找资源的,而打包好的web站点只有一个html页面,不存在其他资源目录下的html,服务器找不到对应页面所以才报404。

此时我们可以在location /中添加配置来讲不同的vue路由重新映射到跟路径指定的html上:

1
2
3
4
5
location / {
root html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}

如果给出的file都没有匹配到,则重新请求最后一个参数给定的uri,就是新的location匹配

常见的变量:

  1. $uri 指当前的请求URI,不包括任何参数,反映任何内部重定向或index模块所做的修改
  2. $args 当前请求的参数,即“?”后的宇符串
  3. $arg_xxx 当前请求里的某个参数,“arg ”后是参数的名字
  4. $http_xxx 当前请求里的 xxx 头部对应的值
  5. $sent_http_xxx 返回给客户端的响应头部对应的值
  6. $remote_addr 客户端IP 地址。
  7. $http_cookie 获取cookie值
  8. $cookie_xxx 当前请求的cookie xxx对应的值
  9. $request_uri 浏览器发起的不作任何修改的请求的url中的path 如在www.baidu.com/p1/file?d=111, 其值为/p1/file?d=111
  10. $request_method 请求方法

GoAccess

GoAccess是一款开源、实时,运行在命令行终端下的web日志分析工具。该工具提供快速、多样的HTTP状态统计,可以令管理员不再纠结于统计各类数据,和繁杂的指令以及一大堆管道/正则表达式说byebye

底层使用C编写

Linux下安装:

1
2
3
4
5
6
wget http://tar.goaccess.io/goaccess-1.2.tar.gz
tar -xzvf goaccess-1.2.tar.gz
cd goaccess-1.2/
./configure
make
make install

然后切换到nginx目录下的log文件夹中,可以看到access.log文件即为nginx的日志文件。

除了格式化的命令行显示外,还支持生成HTML页面,但这一功能需要窝门手动的在Nginx服务器上创建html文件作为容器:

在Nginx目录中的html目录下创建report.html后

开启实时HTML报告分析(webSocket)

1
goaccess access.log -a -o ../html/report.html --real-time-html --log-format=COMBINED

upstream负载均衡配置

upstream字段属于http的子字段,与server字段平级

一个upstream需要设置一个名称,这个名称可以在server里面当作proxy主机使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http: {
upstream node {
# 使用不同端口启动的服务来模拟多服务器
server 127.0.0.1:9001;
server 127.0.0.1:9002;
server 127.0.0.1:9003;
}
server {
# 此时需要把反向代理配置为负载均衡的名称
location / {
proxy_pass http://node;
}
}
}

API代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const express = require('express')
var num = 1
const app = express()

app.get('/list',(req,res)=>{
res.json({
code:200,
message:"Nginx 负载均衡9001"
})
console.log("Nginx 负载均衡9001",num) // 写日志
num++ // 统计访问次数
})
//------------------------------9001
app.listen(9001,()=>{
console.log('9001 success')
})

//-----------------------------------
const express = require('express')
var num = 1
const app = express()

app.get('/list',(req,res)=>{
res.json({
code:200,
message:"Nginx 负载均衡9002"
})
console.log("Nginx 负载均衡9002",num)
num++
})
//------------------------------9002
app.listen(9002,()=>{
console.log('9002 success')
})

//--------------------------------

const express = require('express')
var num = 1
const app = express()

app.get('/list',(req,res)=>{

res.json({
code:200,
message:"Nginx 负载均衡9003"
})
console.log("Nginx 负载均衡9003",num)
num++
})
//------------------------------9003
app.listen(9003,()=>{
console.log('9003 success')
})

默认状态下使用轮询的方式进行负载均衡,可以使用postman对接口进行压力测试,使用PM2启动三个后端服务后,查看PM2的日志可以发现三个接口的访问次数时相同的。

权重并发

当服务器性能不同时可能需要按照权重来进行负载均衡,此时通过为每个服务器设置权重值来开启:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http: {
upstream node {
# 使用不同端口启动的服务来模拟多服务器
server 127.0.0.1:9001 weight=3;
server 127.0.0.1:9002 weight=2;
server 127.0.0.1:9003 weight=1;
}
server {
# 此时需要把反向代理配置为负载均衡的名称
location / {
proxy_pass http://node;
}
}
}

权重越大服务器承载的并发就越高

压力测试结束后可以看到9001端口的访问次数最大,9002其次,9003最少

备用服务器

backup是备用服务器参数,可以为一个upstream设置一个backup的server,在生产server全部都出问题之后,可以自动切换到备用server上,为回复服务争取时间,该功能通过设置fail_timeout字段设置容忍时间,backup字段设置备用服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http: {
upstream node {
# 使用不同端口启动的服务来模拟多服务器
server 127.0.0.1:9001 fail_timeout=60;
server 127.0.0.1:9002 fail_timeout=20;
server 127.0.0.1:9003 backup;
}
server {
# 此时需要把反向代理配置为负载均衡的名称
location / {
proxy_pass http://node;
}
}
}

从PM2日志可以观察到网络正常的情况下9001端口和9002端口的服务访问次数相同,9003没有被访问过

评论