Эта статья не о том, как развернуть проект онлайн, а о том, как автоматизировать его онлайн.
Разработана система управления требованиями и релизами.
С помощью этой системы вы можете создать спрос, создать план выпуска, создать ветку, развернуть в тестовой среде и развернуть в рабочей среде, официально запустить, объединить код и так далее.
1. Функциональный дизайн
Облачный сервер Alibaba за 9,9 юаня работает очень медленно, но этого вполне достаточно для завершения проекта. Используйте 3 каталога для моделирования различных сред.
содержание | хранить |
---|---|
project | Храните все элементы, такие как внешний и внутренний код этой системы. |
pre-dir | Предварительная среда, конечно же, предназначена для тестирования. |
pro-dir | В производственной среде проблем с тестом нет, а развертывание происходит онлайн. |
Одна картинка стоит тысячи слов.
2. Страница системы
мое задание
Получив новое требование, вы можете создать новое требование и создать ветку разработки.
очередь выпуска
После завершения разработки вы можете перейти к очереди релиза и развернуть его в предрелизной среде для тестирования. Тесты могут получить доступ к тестовому коду, указав файл cookie. Наконец, будет выполнено онлайн-развертывание.
Информационный проект
2. Стек технологий
Стек передовых технологий
Vue + elementUI, конкретный код находится вGithub, если вам интересно, можете посмотреть и нажать на звездочку~✨
Стек серверных технологий
Очень распространен Node.js (Koa2) + Mysql + Redis + Pm2. Конкретный код находится вGithub, если вам интересно, можете посмотреть и нажать на звездочку~✨
3. Redis и конфигурация сеанса
// 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",
}));
4. Конфигурация маршрутизатора
Для того, чтобы Router выглядел более элегантно, он также через middleware
// 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;
}
}
}
6. Некоторое промежуточное ПО
Общие настройки 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();
}
}
}
Семь, рабочие сценарии оболочки
Например, создать ветку проекта
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,
}
Вы можете вызвать его на уровне модели~
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;
}
}
9. Доменное имя
Не покупая доменное имя, измените хосты локально (вы можете использовать инструмент напрямую)
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. Вместо того, чтобы напрямую смотреть на другие проекты, как раньше, я учился шаг за шагом.Хотя они все скины, я чувствую, что моя система знаний намного богаче. Я также многое узнал о непрерывной интеграции.Конечно, небольшие проекты, которые я делаю, относительно просты ~ Если вам это нравится, пожалуйста, поставьте лайк и поддержите его, (^__^) Ух……
Подробное использование находится вИнтерфейсный проект,серверный проект, если вам интересно, можете посмотреть и нажать на звездочку~✨