本篇文章讲的不是如何把一个项目部署上线,而是如何自动化上线。

开发了一个需求管理和发布系统。

通过这个系统,可以创建需求、创建发布计划、创建分支、部署到测试环境、部署到生产环境、正式上线、合并代码等。

一、功能设计

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.js
const 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_node
map $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/bash

cd $1
git pull origin master
git checkout -b $2
git 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哈~✨

 以上所述是小编给大家介绍的自动化部署项目详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对Devmax网站的支持!

如何自动化部署项目?折腾服务器之旅~的更多相关文章

  1. CentOS 8.2服务器上安装最新版Node.js的方法

    这篇文章主要介绍了CentOS 8.2服务器上安装最新版Node.js的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  3. Node.js调试技术总结分享

    Node.js是一个可以快速构建网络服务及应用的平台。该平台的构建是基于Chrome's JavaScript runtime,也就是说,实际上它是对Google V8引擎(应用于Google Chrome浏览器)进行了封装。 今天介绍Node.js调式目前有几种技术,需要的朋友可以参考下。

  4. node.js实现http服务器与浏览器之间的内容缓存操作示例

    这篇文章主要介绍了node.js实现http服务器与浏览器之间的内容缓存操作,结合实例形式分析了node.js http服务器与浏览器之间的内容缓存原理与具体实现技巧,需要的朋友可以参考下

  5. 教你如何使用node.js制作代理服务器

    本文介绍了如何使用node.js制作代理服务器,图文并茂,十分的详细,代码很简洁易懂,这里推荐给大家。

  6. node.js中的fs.openSync方法使用说明

    这篇文章主要介绍了node.js中的fs.openSync方法使用说明,本文介绍了fs.openSync方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下

  7. Node.js+ELK日志规范的实现

    这篇文章主要介绍了Node.js+ELK日志规范的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. node.js爬虫框架node-crawler初体验

    这篇文章主要介绍了node.js爬虫框架node-crawler的相关资料,帮助大家利用node.js进行爬虫,感兴趣的朋友可以了解下

  9. node.js中的fs.existsSync方法使用说明

    这篇文章主要介绍了node.js中的fs.existsSync方法使用说明,本文介绍了fs.existsSync方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下

  10. 说说如何利用 Node.js 代理解决跨域问题

    这篇文章主要介绍了Node.js代理解决跨域问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

随机推荐

  1. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  2. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  3. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  4. nodejs模块学习之connect解析

    这篇文章主要介绍了nodejs模块学习之connect解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. nodejs npm package.json中文文档

    这篇文章主要介绍了nodejs npm package.json中文文档,本文档中描述的很多行为都受npm-config(7)的影响,需要的朋友可以参考下

  6. 详解koa2学习中使用 async 、await、promise解决异步的问题

    这篇文章主要介绍了详解koa2学习中使用 async 、await、promise解决异步的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. Node.js编写爬虫的基本思路及抓取百度图片的实例分享

    这篇文章主要介绍了Node.js编写爬虫的基本思路及抓取百度图片的实例分享,其中作者提到了需要特别注意GBK转码的转码问题,需要的朋友可以参考下

  8. CentOS 8.2服务器上安装最新版Node.js的方法

    这篇文章主要介绍了CentOS 8.2服务器上安装最新版Node.js的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  9. node.js三个步骤实现一个服务器及Express包使用

    这篇文章主要介绍了node.js三个步骤实现一个服务器及Express包使用,文章通过新建一个文件展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下

  10. node下使用UglifyJS压缩合并JS文件的方法

    下面小编就为大家分享一篇node下使用UglifyJS压缩合并JS文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

返回
顶部