赞
踩
系统架构设计的四层抽象:
总体结构:
一、session不足:
解决:将session存储在Redis中
二、为何session适合用Redis存储
三、开启redis服务:
打开一个 cmd 窗口 使用 cd 命令切换目录到redis目录下 运行
redis-server.exe redis.windows.conf
如何配置反向代理:
nginx.conf
配置文件:
location / {
# 如果是根目录(即 http://localhost:8080)则代理到 8001 端口
proxy_pass http://localhost:8001;
}
location /api/ {
# 如果是访问接口,则代理到 8000 端口
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
}
http://localhost:8080/index.html
即可ps:
start nginx
http-server -p8001
npm run dev
Nginx命令
构建流程
npm install -g express -generator
全局安装express命令安装工具express 项目名
npm install
安装组件npm start
启动项目(服务器)npm i nodemon cross-env
写自己的业务逻辑:
blog.js
)引入app.js
文件中,并使用app.use
注册我们的路由相对于原生nodejs:
req.query
获取get传过来的参数,通过req.body
获取 post传过来的参数res.json
直接返回json数据给客户端express-session
、connect-redis
、登陆中间件morgan
来记录日志,根据配置决定将日志输出到控制台还是文件中构建流程
npm install koa-generator -g
全局安装express命令安装工具Koa2 项目名
npm install
安装组件npm i cross-env
npm run dev
启动项目(服务器)相对于express和原生nodejs:
ctx.query
获取get传过来的参数,通过ctx.request.body
获取 post传过来的参数ctx.body
直接返回json数据给客户端async/await
来实现中间件await next()
来执行下一个中间件express
,koa2在记录日志时要手动安装koa-morgan
插件req, res, next
function loginCheck(req, res, next) {
console.log('模拟登陆成功')
next()
}
app.use()
、app.get()
、app.post()
注册中间件next()
的执行一个一个的往下串联下一个中间件实现原理思路:
app.use
用来注册中间件,先收集起来http
请求,根据path
、method
判断触发哪些中间件next()
机制,即上一个通过next()
触发下一个// 实现类似 express 的中间件 const http = require('http') const slice = Array.prototype.slice class LikeExpress { constructor() { // 收集存放中间件的列表 this.routes = { all: [], // app.use(...) get: [], // app.get(...) post: [] // app.post(...) } } register(path) { const info = {} if (typeof path === 'string') { info.path = path // 从第二个参数开始,转换为数组,存入 stack info.stack = slice.call(arguments, 1) } else { info.path = '/' // 从第一个参数开始,转换为数组,存入 stack info.stack = slice.call(arguments, 0) } return info } // 中间件注册和收集 use() { const info = this.register.apply(this, arguments) this.routes.all.push(info) } get() { const info = this.register.apply(this, arguments) this.routes.get.push(info) } post() { const info = this.register.apply(this, arguments) this.routes.post.push(info) } // 通过当前 method 和 url 来匹配当前路由可执行的中间件 match(method, url) { let stack = [] if (url === '/favicon.ico') { return stack } // 获取 routes let curRoutes = [] curRoutes = curRoutes.concat(this.routes.all) curRoutes = curRoutes.concat(this.routes[method]) curRoutes.forEach(routeInfo => { if (url.indexOf(routeInfo.path) === 0) { // url === '/api/get-cookie' 且 routeInfo.path === '/' // url === '/api/get-cookie' 且 routeInfo.path === '/api' // url === '/api/get-cookie' 且 routeInfo.path === '/api/get-cookie' stack = stack.concat(routeInfo.stack) } }) return stack } // 核心的 next 机制 handle(req, res, stack) { const next = () => { // 拿到第一个匹配的中间件 const middleware = stack.shift() if (middleware) { // 执行中间件函数 middleware(req, res, next) } } next() } callback() { return (req, res) => { res.json = (data) => { res.setHeader('Content-type', 'application/json') res.end( JSON.stringify(data) ) } const url = req.url const method = req.method.toLowerCase() const resultList = this.match(method, url) this.handle(req, res, resultList) } } listen(...args) { const server = http.createServer(this.callback()) server.listen(...args) } } // 工厂函数 module.exports = () => { return new LikeExpress() }
async
函数,参数为(ctx, next)
app.use(async (ctx, next) => {
await next();
ctx.body = 'Hello World';
});
实现思路:
app.use
来注册中间件,先收集起来next
机制,即上一个通过await next()
触发下一个中间件method
和path
的判断<!--实现类似 靠中间件--> const http = require('http') // 组合中间件 function compose(middlewareList) { return function (ctx) { function dispatch(i) { const fn = middlewareList[i] try { return Promise.resolve( fn(ctx, dispatch.bind(null, i + 1)) // promise ) } catch (err) { return Promise.reject(err) } } return dispatch(0) } } class LikeKoa2 { constructor() { this.middlewareList = [] } // 收集中间件列表 use(fn) { this.middlewareList.push(fn) return this } createContext(req, res) { const ctx = { req, res } ctx.query = req.query return ctx } handleRequest(ctx, fn) { return fn(ctx) } callback() { const fn = compose(this.middlewareList) return (req, res) => { const ctx = this.createContext(req, res) return this.handleRequest(ctx, fn) } } listen(...args) { const server = http.createServer(this.callback()) server.listen(...args) } } module.exports = LikeKoa2
restart
,而不是说系统出错之后其他用户就无法使用了下载安装
cnpm i pm2 -g
配置命令
"prd": "cross-env NODE_ENV=production pm2 start app.js"
启动
npm run prd
常用命令
pm2配置文件
{
"apps": {
"name": "pm2-test-server", // 进程名
"script": "app.js", //用框架就是'bin/www'
"watch": true, // 监听文件变化,是否自动重启
"ignore_watch": [ // 哪些文件不需要重启
"node_modules",
"logs"
],
"instances": 4, // 进程个数,这里
"error_file": "logs/err.log", // 错误日志存放位置
"out_file": "logs/out.log", // 本来打印在控制台的console自定义存放在文件里
"log_date_format": "YYYY-MM-DD HH:mm:ss" // 日志的时间戳
}
}
为何使用多进程
多进程和redis
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。