Nginx + Node + Vue 部署初試

趁着爸媽做年夜飯之前,把之前做的筆記貼出來,新的一年到了,祝大家

Rich overnight

Nginx + Node + Vue 部署初試

知乎

個人博客

Github

日常學習筆記

Nginx
  1. 定義

    異步框架的 Web服務器,也可以用作反向代理負載平衡器 , HTTP緩存, 媒體流等的開源軟件。它最初是一個旨在實現最高性能和穩定性的Web服務器。除了HTTP服務器功能外,NGINX還可以用作電子郵件(IMAPPOP3SMTP)的代理服務器以及HTTPTCPUDP服務器的反向代理和負載平衡器。

  2. 特點

    • 更快
    • 高擴展性, Nginx的模塊都是嵌入到二進制文件中執行
    • 高可靠性
    • 低內存消耗
    • 單機支持10萬次的併發連接
    • 熱部署, master管理進行與work工作進程分離設計,因此具備熱部署功能
    • 最自由的BSD許可協議
  3. 功能

    • 靜態服務(css , js , html, images, videos
    • SSLTLS SNI 支持
    • HTTP/HTTPS, SMTP, IMAP/POP3 反向代理
    • FastCGI反向代理
    • 負載均衡
    • 頁面緩存(CDN
    • 支持gzipexpirse
    • 支持 keep-alive 和管道連接
    • 基於 PCRErewrite 重寫模塊
    • 帶寬限制
    • 基於IP 和名稱的虛擬主機服務
    • 支持訪問速率、併發限制
    • 反向代理(適用2000WPV、併發連接1W/秒),簡單的負載均衡和容錯
    • 基於客戶端 IP 地址和 HTTP 基本認證的訪問控制
Mac 安裝Nginx
// 推薦使用`brew`, 安裝`homebrew`
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
// Homebrew 安裝 Nginx 
brew install nginx
// Mac 下 Nginx的目錄
cd /usr/local/etc/nginx
ll -al
vim nginx.conf

homebrew詳見

cd-nginx

Nginx 參數列表
配置參數屬性 解釋說明 參數列表
user 設置nginx服務的系統使用用戶 nobody(注意:此處用戶如果比啓動Nginx的用戶權限低,你需要使用當前用戶重啓Nginx)
nginx -s stop 關閉nginx-> nginx 啓動-> `ps aux
grep nginx`查看啓動用戶
worker_processes 開啓的線程數 一般與服務器核數保持一致
error_log 定位全局錯誤日誌文件 錯誤日誌定義等級,[ debug \ info notice \ warn \ error \ crit ],debug輸出最多,crir輸出最少
pid 指定進程id的存儲文件位置
worker_rlimit_nofile 指定一個nginx進程打開的最多文件描述符數目,受系統進程的最大打開文件數量限制
events 包含Nginx中所有處理連接的設置
http Nginx http處理的所有核心特性
Event
配置參數屬性 解釋說明 參數列表
worker_connections 定義每個進程的最大連接數,受系統進程的最大打開文件數量限制 單個後臺worker process進程的最大併發鏈接數 (最大連接數= worker_processes worker_connections)
在反向代理環境下:<br/>最大連接數 = worker_processes
worker_connections / 4
use 工作進程數 [ epoll \ /dev/poll \ poll \ eventport \ kqueue \ select \ rtsig ]
multi_accept 一個新連接通知後接受儘可能多的連接 on / off
accept_mutex 開啓或者禁用使用互斥鎖來打開sockets on / off

Event Use支持的事件模型

events-use

Events詳見

HTTP
配置參數屬性 解釋說明 參數列表
include 主模塊指令,實現對配置文件所包含的文件的設定,可以減少主配置文件的複雜度,DNS主配置文件中的zonerfc1912,acl基本上都是用include語句
default_type 核心模塊指令 默認設置爲二進制流,也就是當文件類型未定義時使用這種方式
log_format 日誌格式的設定 日誌格式的名稱,可自行設置,後面引用
access_log 引用日誌 引用log_format設置的名稱
keepalive_timeout 設置客戶端連接保存活動的超時時間 0是無限制
sendfile 開啓高效文件傳輸模式 on / off
tcp_nopush 開啓防止網絡阻塞 on / off
tcp_nodelay 開啓防止網絡阻塞 on / off
upstream 負載均衡
server Nginx的server虛擬主機配置
Upstream
配置參數屬性 解釋說明
輪詢(默認) 每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
weight 指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的情況
ip_hash 每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
fair(第三方) 按後端服務器的響應時間來分配請求,響應時間短的優先分配。
url_hash(第三方) 按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。

weight 默認爲1.weight越大,負載的權重就越大。

Nginx Upstream 狀態

例如:

upstream news {
    server 127.0.0.1:9527 backup;
    server 127.0.0.1:9527 weight=1 max_fails=2 fail_timeout=3;
    ...
}
配置參數屬性 解釋說明
backup 預留的備份服務器
down 當前的server暫時不參與負載均衡
fail_timeout 經過max_fails 失敗後,服務暫停的時間
max_conns 限制最大的接收的連接數
max_fails 允許請求失敗的次數

use location:在server中添加

proxy_pass http://127.0.0.1:9527;
// 因爲我的API接口是這個,such as /api/profile
// location 具體匹配規則詳見後面
location ~ /api/ {
    proxy_pass http://127.0.0.1:9527;
}
Server
配置參數屬性 解釋說明 參數列表
listen 監聽端口 http -> 80 / https -> 443
server_name 設置主機域名 localhost
charset 設置訪問的語言編碼
access_log 設置虛擬主機訪問日誌的存放路徑及日誌的格式
location 設置虛擬主機的基本信息
Location
配置參數屬性 解釋說明 參數列表
root 設置虛擬主機的網站根目錄 Vue項目的根目錄/Users/rainy/Desktop/MyWork/Work/cloudwiz-website/dist
index 設置虛擬主機默認訪問的網頁 index.html index.htm
proxy 通過不同協議將請求從NGINX傳遞到代理服務器
  • =: 開頭表示精確匹配,如 api 中只匹配根目錄結尾的請求,後面不能帶任何字符串.
  • ^~ :開頭表示uri以某個常規字符串開頭,不是正則匹配.
  • ~: 開頭表示區分大小寫的正則匹配.
  • ~*: 開頭表示不區分大小寫的正則匹配.
  • / : 通用匹配, 如果沒有其它匹配,任何請求都會匹配到.

匹配優先級(高到低)

  1. location =
  2. location 完整路徑
  3. location ^~ 路徑
  4. location ~,~* 正則順序
  5. location 部分起始路徑
  6. /

詳見Location配置

Reverse Proxy

NGINX代理請求時,它會將請求發送到指定的代理服務器,獲取響應並將其發送回客戶端。可以使用指定的協議將請求代理到HTTP服務器(另一個NGINX服務器或任何其他服務器)或非HTTP服務器(可以運行使用特定框架(如PHPPython)開發的應用程序)。

location  / some / path /  {
    proxy_pass  http://www.example.com:8080;
    
    proxy_set_header  Host  $ host ; 
    proxy_set_header  X-Real-IP  $ remote_addr ;
    
    // 禁用特定位置的緩衝
    proxy_buffering  off ;
    proxy_buffers  16  4k ; 
    proxy_buffer_size  2k ;
    
    proxy_bind  127.0.0.2 ; // IP地址也可以用變量指定
}

將請求傳遞給非HTTP代理服務器,**_pass應使用相應的指令:

配置參數屬性 解釋說明 參數列
proxy_pass 將請求傳遞給HTTP代理服務器
proxy_set_header 傳遞請求標頭 默認情況下,NGINX在代理請求中重新定義兩個頭字段“Host”和“Connection”,並刪除其值爲空字符串的頭字段。“Host”設置爲$proxy_host變量,“Connection”設置爲close
proxy_buffering 負責啓用和禁用緩衝 on / off
proxy_buffers 請求分配的緩衝區的大小和數量
proxy_buffer_size 代理服務器的響應的第一部分存儲在單獨的緩衝區大小 通常包含一個相對較小的響應頭,並且可以比其餘響應的緩衝區小。
proxy_bind 接受來自特定IP網絡或IP地址範圍的連接 指定proxy_bind必要網絡接口的指令和IP地址

詳見Proxy

全局變量Global Variable
變量名 變量含義
$args 請求中的參數
$content_length HTTP請求信息裏的Content-Length
$content_type 請求信息裏的Content-Type
$host 請求信息中的Host,如果請求中沒有Host行,則等於設置的服務器名
$http_cookie cookie 信息
$http_referer 引用地址
$http_user_agent 客戶端代理信息
$remote_addr 客戶端地址
$remote_port 客戶端端口號
$remote_user 客戶端用戶名,認證用
$request_method 請求的方法,比如GETPOST
$request_uri 完整的原始請求URI(帶參數)
$scheme 請求方案,httphttps
$server_addr 接受請求的服務器的地址,如果沒有用listen指明服務器地址,使用這個變量將發起一次系統調用以取得地址(造成資源浪費);
$server_protocol 請求的協議版本,HTTP/1.0HTTP/1.1
$uri 請求中的當前URI, $uri在請求處理期間 ,值可能會發生變化,例如在執行內部重定向或使用索引文件時

全局變量詳見Alphabetical index of variables

修改 http server中的配置

nginx-config

啓動Nginx

nginx
ps -ef | grep nginx

重啓Nginx

nginx -s reload

關閉Nginx

nginx -s stop

因爲我已經啓動了,所以就重啓一下Nginx即可

nginx-reload

Linux安裝Nginx

Linux安裝

常見的Linux命令

使用pstree查看當前服務器啓動的進程

pstree

pstree

查找Nginx的位置

ps -aux | grep nginx

server-where-nginx

進入nginx的目錄

212-server-nginx

nginx-conf

然後配置nginx.conf文件即可

Docker安裝Nginx
  1. 查找 Docker Hub 上的 nginx鏡像

    docker search nginx

    docker-search

  2. 拉取官方鏡像

    docker pull nginx
  3. 查看當前鏡像

    docker images nginx

    docker-images

Server Tree
tree -C -L 3 -I '*node_modules*'

├── server
│   ├── app.js
│   ├── db
│   │   ├── db.js
│   │   └── newsSql.js
│   ├── package-lock.json
│   ├── package.json
│   └── routers
│       ├── news.js
│       └── router.js

file-tree

Node Server

npm init
npm install express mysql body-parser -S
  1. app.js

    const express = require('express')
    const bodyParser = require('body-parser')
    const app = express()
    const router = require('./routers/router')
    
    const PORT = 9527
    
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({ extended: true }))
    
    app.use(router)
    
    app.listen(PORT, () => {
      console.log(`Listen port at ${PORT}`)
    })
    
  2. db.js -> Mysql配置

    module.exports = {
      mysql: {
        host: 'localhost',
        user: 'root',
        password: 'xxxx',
        database: 'test',
        port: '3306'
      }
    }
  3. router.js

    const express = require('express')
    const router = express.Router()
    const news = require('./news')
    
    router.get('/api/news/queryAll', (req, res, next) => {
      news.queryAll(req, res, next)
    })
    
    router.get('/api/news/query', (req, res, next) => {
      news.queryById(req, res, next)
    })
    
    router.post('/api/news/add', (req, res, next) => {
      news.add(req, res, next)
    })
    
    router.post('/api/news/update', (req, res, next) => {
      news.update(req, res, next)
    })
    
    router.delete('/api/news/deleteNews', (req, res, next) => {
      news.deleteNews(req, res, next)
    })
    
    module.exports = router
  4. newSql.js

    module.exports = {
      createNews: `CREATE TABLE news (
        id int(255) NOT NULL AUTO_INCREMENT,
        type varchar(255) CHARACTER SET utf8 NOT NULL,
        title varchar(255) CHARACTER SET utf8 NOT NULL,
        description varchar(255) CHARACTER SET utf8 NOT NULL,
        occur_time varchar(255) CHARACTER SET utf8 NOT NULL,
        url varchar(255) NOT NULL,
        newsImg varchar(255) NOT NULL,
        PRIMARY KEY (id)
      )`,
      queryAll: 'SELECT * FROM news',
      queryById: 'SELECT * FROM news WHERE id = ?',
      add: 'INSERT INTO news (type, title, description, occur_time, url, newsImg) VALUES (?, ?, ?, ?, ?, ?)',
      update: 'UPDATE news SET type = ?, title = ?, description = ?, occur_time = ?, url = ?, newsImg = ? WHERE id = ?',
      delete: 'DELETE FROM news WHERE id = ?'
    }
  5. news.js

    const mysql = require('mysql')
    const db = require('../db/db')
    const $newsSql = require('../db/newsSql')
    
    let pool = mysql.createPool(db.mysql)
    
    let queryAll = (req, res, next) => {
      pool.getConnection((error, connect) => {
        if (error) {
          throw error
        } else {
          connect.query($newsSql.queryAll, (error, data) => {
            if (error) {
              throw error
            }
            res.json({
              code: '200',
              msg: 'success',
              data
            })
            connect.release()
          })
        }
      })
    }
    
    let queryById = (req, res, next) => {
      let id = +req.query.id
      pool.getConnection((error, connect) => {
        if (error) {
          throw error
        } else {
          connect.query($newsSql.queryById, id, (error, data) => {
            if (error) {
              throw error
            }
            res.json({
              code: '200',
              msg: 'success',
              data
            })
            connect.release()
          })
        }
      })
    }
    
    let add = (req, res, next) => {
      let rb = req.body
      let params = [rb.type, rb.title, rb.description, rb.occur_time, rb.url, rb.newsImg]
      pool.getConnection((error, connect) => {
        if (error) {
          throw error
        } else {
          connect.query($newsSql.add, params, (error, data) => {
            if (error) {
              throw error
            }
            res.json({
              code: '200',
              msg: 'success'
            })
            connect.release()
          })
        }
      })
    }
    
    let update = (req, res, next) => {
      let rb = req.body
      let params = [rb.type, rb.title, rb.description, rb.occur_time, rb.url, rb.newsImg, rb.id]
      pool.getConnection((error, connect) => {
        if (error) {
          throw error
        } else {
          connect.query($newsSql.update, [...params], (error, data) => {
            if (error) {
              throw error
            }
            res.json({
              code: '200',
              msg: 'success'
            })
            connect.release()
          })
        }
      })
    }
    
    let deleteNews = (req, res, next) => {
      let id = +req.query.id
      pool.getConnection((error, connect) => {
        if (error) {
          throw error
        } else {
          connect.query($newsSql.delete, id, (error, data) => {
            if (error) {
              throw error
            }
            res.json({
              code: '200',
              msg: 'success'
            })
            connect.release()
          })
        }
      })
    }
    
    module.exports = {
      queryAll,
      queryById,
      add,
      update,
      deleteNews
    }
Vue配置代理以及使用api
  1. config/index.js 修改proxyTable

    module.exports = {
      dev: {
        proxyTable: {
          '/api': {
            target: 'http://127.0.0.1:9527',
            changeOrigin: true,
            pathRewrite: {
              '^/api': '/api'
            }
          }
        }
      }
    }
  2. 使用axios調用接口

    import axios from 'axios'
    export default {
      created () {
        this._getAllNews()
      },
      methods: {
        _getAllNews () {
          axios.get('/api/news/queryAll').then(res => {
                if (+res.data.code === SCC_CODE) {
                  this.news = res.data.data
                }
              })
          }
        }
    }
Vue build打包
npm run build

vue-build

因爲我的Server端是Express寫的,啓動Server需要使用Node,所以我們需要在服務器上安裝Node.

Linux安裝Node 8.x
# Using Ubuntu
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -sL https://deb.nodesource.com/setup_8.x | bash -
apt-get install -y nodejs

# Using Centos
curl -sL https://rpm.nodesource.com/setup_8.x | bash -
yum install -y nodejs

具體安裝各版本的Node詳見

啓動Node

此處我之前的命令執行錯誤,所以我需要kill這個進程

nohup node website/server/app.js &

node-nohup

nohup:可以將程序以忽略掛起信號的方式運行起來,被運行的程序的輸出信息將不會顯示到終端。

無論是否將 nohup 命令的輸出重定向到終端,輸出都將附加到當前目錄的 nohup.out文件中。如果當前目錄的 nohup.out 文件不可寫,輸出重定向到$HOME/nohup.out文件中。如果沒有文件能創建或打開以用於追加,那麼 command 參數指定的命令不可調用。如果標準錯誤是一個終端,那麼把指定的命令寫給標準錯誤的所有輸出作爲標準輸出重定向到相同的文件描述符。

nohup-out

到這裏,我們的WebNode ServerNginx都已經配置並啓動好了,我們只需要到瀏覽器輸入你的服務器IP:8080即可.

Nginx衆多概念詳見官方詞彙表

nginx-glossary

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章