本篇文章講的不是如何把一個項目部署上線,而是如何自動化上線。
開發了一個需求管理和發布系統。
通過這個系統,可以創建需求、創建發布計劃、創建分支、部署到測試環境、部署到生產環境、正式上線、合并代碼等。
一、功能設計
9.9元的阿里云服務器真的很慢,但還是足夠折騰完這個項目。
用3個目錄來模擬不同的環境。
目錄 | 存放 |
---|---|
project | 存放所有的項目,比如本系統的前后端代碼。 |
pre-dir | 預發環境,當然是用來測試的。 |
pro-dir | 生產環境,測試沒問題,部署上線。 |
一圖勝千言。
二、系統頁面
我的任務
接到一個新的需求,可以新建一個需求,并創建開發分支。
發布隊列
開發結束之后,便可以到發布隊列中,部署到預發環境進行測試。 測試通過指定Cookie 就可以訪問到測試的代碼。最終再進行線上部署。
項目信息
二、技術棧
前端技術棧
Vue + elementUI,具體代碼在Github,感興趣的可以看下并點個star哈~?
服務端技術棧
非常常見的Node.js(Koa2) + Mysql + Redis + Pm2。
具體代碼在Github,感興趣的可以看下并點個star哈~?
三、Redis和Session配置
// utils/Store.jsconst Redis = require("ioredis");const { Store } = require("koa-session2"); class RedisStore extends Store { constructor() { super(); this.redis = new Redis(); } async get(sid, ctx) { let data = await this.redis.get(`SESSION:${sid}`); return JSON.parse(data); } async set(session, { sid = this.getID(24), maxAge = 1000 * 60 * 60 } = {}, ctx) { try { console.log(`SESSION:${sid}`); // Use redis set EX to automatically drop expired sessions await this.redis.set(`SESSION:${sid}`, JSON.stringify(session), 'EX', maxAge / 1000); } catch (e) {} return sid; } async destroy(sid, ctx) { return await this.redis.del(`SESSION:${sid}`); }} module.exports = RedisStore;
// 入口文件const session = require("koa-session2");const Store = require("./utils/Store.js");// session配置app.use(session({ store: new Store(), key: "SESSIONID",}));
四、Router配置
為了Router看起來更優雅,也是通過中間件
// 1、middleware配置文件const routers = require('../routers');module.exports = (app) => { app.use(routers());}// 2、index.js入口文件const middleware = require('./middleware');middleware(app);// 3、routers 注冊文件const Router = require('koa-router');const router = new Router();const koaCompose = require('koa-compose');// 接口入口const {insertDemand} = require('../controllers/demand/insertDemand');const {deleteDemand} = require('../controllers/demand/deleteDemandByDid');const {updateDemand} = require('../controllers/demand/updateDemandByDid');// 加前綴router.prefix('/api');module.exports = () => { // 新增需求 router.get('/insertDemand', insertDemand); // 刪除需求 router.get('/deleteDemand', deleteDemand); return koaCompose([router.routes(), router.allowedMethods()]);}
五、nginx配置
最頭痛的就是nginx配置了,因為不是很熟悉,一直在試錯、踩坑。不過還好終于成功了!
前后端項目通過Nignx提供服務,Node服務通過Nginx轉發,主要是為了驗證各種環境。
如果不設置Cookie,默認訪問的就是線上環境,設置Cookie 就會走到預發布測試環境,用于測試。
# cookie 取TEST 賦值給$proxy_nodemap $cookie_TEST $proxy_node { default ""; "1" "1"; "2" "2"; "3" "3";}# 發布管理系統前端設置server { listen 80; server_name test.xue.com; if ($proxy_node = ''){ set $dollar "/data/pro-dir/dandelion/dist/"; } if ($proxy_node = "1") { set $dollar "/data/pre-dir/dandelion/dist/"; } location / { root $dollar; index index.html; try_files $uri $uri/ /index.html; }}# 發布管理系統后端設置# 反向代理到node服務server { listen 80; server_name m.xue.com; if ($proxy_node = ''){ set $dollar "/data/pro-dir/study-demo/"; } if ($proxy_node = "2") { set $dollar "/data/pre-dir/study-demo/"; } location / { root $dollar; index index.html; }}# demo項目前端設置server { listen 80; server_name api.xue.com; location / { if ($proxy_node = "") { set $from 3001; proxy_pass http://47.107.188.55:3001; } if ($proxy_node = "3") { set $from 3002; proxy_pass http://47.107.188.55:3002; } }}
六、一些中間件
常用的HTTP設置
解決跨域,OPTIONS請求,攜帶Cookie憑證等問題。
module.exports = () => { return async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', 'http://test.xue.com'); ctx.set('Access-Control-Allow-Credentials', true); ctx.set('Access-Control-Allow-Headers', 'content-type'); ctx.set('Access-Control-Allow-Methods', 'OPTIONS, GET, HEAD, PUT, POST, DELETE, PATCH'); // 這個響應頭的意義在于,設置一個相對時間,在該非簡單請求在服務器端通過檢驗的那一刻起, // 當流逝的時間的毫秒數不足Access-Control-Max-Age時,就不需要再進行預檢,可以直接發送一次請求。 ctx.set('Access-Control-Max-Age', 3600 * 24); if (ctx.method == 'OPTIONS') { ctx.body = 200; } else { await next(); } }}
登錄
這個系統屬于強制登錄的,登錄統一進行了處理。
const Store = require("../../utils/Store");const redis = new Store();module.exports = () => { return async (ctx, next) => { // 白名單 if (ctx.request.url === '/api/login') { return await next(); } const SESSIONID = ctx.cookies.get('SESSIONID'); if (!SESSIONID) { return ctx.body = { mes: '沒有攜帶SESSIONID~', data: '', err_code: 1, success: false, }; } const redisData = await redis.get(SESSIONID); if (!redisData) { return ctx.body = { mes: 'SESSIONID已經過期~', data: '', err_code: 1, success: false, }; } if (redisData && redisData.uid) { console.log(`登錄了,用戶uid為${redisData.uid}`); await next(); } }}
七、操作shell腳本
舉個例子,創建項目分支
let path = ''; // 項目路徑// 創建分支const branch_name = `branch_${new Date().getTime()}`;cp.execSync(`/data/dandelion-server/shell/createBranch.sh ${path} ${branch_name}`);
#!/bin/bashcd $1git pull origin mastergit checkout -b $2git push --set-upstream origin $2
八、連接數據庫
config.js配置文件
let dbConf = null;const DEV = { database: 'dandelion', //數據庫 user: 'root', //用戶 password: '123456', //密碼 port: '3306', //端口 host: '127.0.0.1' //服務ip地址}const PRO = { database: 'dandelion', //數據庫 user: 'root', //用戶 password: '123456', //密碼 port: '3306', //端口 host: 'xx.xx.xx.xx' //服務ip地址}dbConf = PRO; //這個可以通過判斷區分開發環境module.exports = dbConf;
數據庫連接文件
const mysql = require('mysql');const dbConf = require('./../config/dbConf');const pool = mysql.createPool({ host: dbConf.host, user: dbConf.user, password: dbConf.password, database: dbConf.database,})let query = function( sql, values ) { return new Promise(( resolve, reject ) => { pool.getConnection(function(err, connection) { if (err) { reject( err ) } else { connection.query(sql, values, ( err, rows) => { if ( err ) { reject( err ) } else { resolve( rows ) } connection.release() }) } }) })}module.exports = { query,}
就可以在model層調用了~
const {query} = require('../common/mysql');class UserModel { constructor() {} /** * @description: 根據pid和did創建一個分支 * @param {pid} 項目id * @param {did} 需求id * @param {branch_name} 分支名 * @return: 分支信息 */ async insertBranchInfo(sqlParams) { const sql = 'insert branch_info (pid, bid, branch_name, pub_time) values(?,?,?,?)'; console.log(sql) let data = await query(sql, sqlParams, (err, result) => { return result; }); return data; }}
九、域名
沒有買域名,通過本地修改hosts(可以直接用工具)
47.107.188.xx為服務器IP
47.107.188.xx test.xue.com
47.107.188.xx api.xue.com
47.107.188.xx m.xue.com
總結
算是第一次自己搭建一個完整的項目,從前端到后端。
尤其是后端,作為一個前端小白,從學習如何使用服務器,到Linux/Vim/Shell/Nignx/Pm2/Redis/Session/Mysql/Koa2。沒有像以前一樣,直接拿別的項目看,而是一步一個腳印的學習,雖然也都是皮毛,但是感覺自己的知識體系豐富了很多。也去了解了很多持續集成的知識,當然我做的小項目還是比較簡單的啦~ 喜歡就點個贊鼓勵一下吧,(^__^) 嘻嘻……
詳細的使用都在前端項目、后端項目,感興趣的可以看下并點個star哈~?
以上所述是小編給大家介紹的自動化部署項目詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!
新聞熱點
疑難解答