node实战入门总结

搭建流程(按新建顺序)层层嵌套引入

系统架构设计的四层抽象:

  • 第一层: www.js [开启 Server]
  • 第二层:app.js [通信设置层]
  • 第三层:router.js [业务逻辑层]
  • 第四层:controller.js [数据层]

总体结构:

  • bin/www.js(第一层):node构建服务的基本流程配置,和业务无关。package里面配置好的入口文件
  • app.js(第二层
  • src
    • router(第三层:根据不同路由返回不同数据)
      • blog.js:博客crud接口
      • user.js:用户相关的接口
    • control(第四层:返回数据给到路由这边,只关心数据及其处理,一般是和数据库这边交互)
    • model(数据模型:成功、失败返回的数据格式等)
    • conf:配置
      • db.js:获取环境参数对数据库进行配置,根据开发环境下的和线上环境使用不同的数据库
    • db
      • mysql.js:对数据库的基本操作(连接创建关闭,不涉及业务逻辑)
      • redis.js: 封装redis的set、get操作
    • utils:工具
      • log.js:专门用来写日志的工具
  • logs:日志
    • access.log:存储访问日志
    • event.log:存储一些自定义内容
    • error.log:存储错误内容

记录

session和Redis

一、session不足:

  • session是存储在nodeJS进程的内存中的
  • 进程内存有限,session过大,会把进程挤爆
  • 进程与进程之间内存相互独立,无法共享,因此session也无法在多进程之间共享

解决:将session存储在Redis中

  • Redis 是另外一个服务,和web server的nodeJS 进程没有关系了
  • Redis类似于数据库,也是一个数据仓库,用来存储数据的(可以叫做内存数据库吧)
  • 但是普通数据库的数据是存储在硬盘上的,访问速度慢
  • Redis上的数据是存储在内存中的,访问速度快,但昂贵

二、为何session适合用Redis存储

  • session访问频繁,对性能要求极高
  • session可不考虑断点丢失数据问题(内存的硬伤),因为大不了重新登录
  • session数据量不会太大,一般只是存储用户的个人信息(相比于 MySQL 中 存储的数据)

三、开启redis服务:

打开一个 cmd 窗口 使用 cd 命令切换目录到redis目录下 运行

redis-server.exe redis.windows.conf
接口和前端联调
  • 登陆功能依赖cookie,必须用浏览器来联调(postman无法做到)
  • cookie跨域不共享,前端和server端必须同域
  • 因此需要用到Nginx 做代理,让前后端同域
Nginx介绍
  • 高性能的 web 服务器,开源免费
  • 一般用于做静态服务(CDN)、负载均衡
  • 反向代理

如何配置反向代理:

  1. 要同时开启对应的服务(占用不同端口):nodeJS server服务8000端口(后端接口)、http-server服务8001端口(前端页面)
  2. 监听8080端口
  3. 反向代理配置

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;
}

  1. 通过访问http://localhost:8080/index.html即可

ps:

  • 开启nginx 服务:start nginx
  • 开启http-server服务:http-server -p8001
  • 开启nodeJs server服务:npm run dev

Nginx命令

  • start nginx:启动nginx服务
  • nginx -t:测试配置文件nginx.conf 语法是否正确

express搭建

构建流程

  1. npm install -g express -generator全局安装express命令安装工具
  2. express 项目名
  3. npm install 安装组件
  4. npm start启动项目(服务器)
  5. npm i nodemon cross-env

写自己的业务逻辑:

  1. 新建路由文件,针对不同路由进行业务逻辑处理
  2. 将新建的路由文件(比如blog.js)引入app.js文件中,并使用app.use注册我们的路由

相对于原生nodejs:

  • 直接通过req.query获取get传过来的参数,通过req.body获取 post传过来的参数
  • 通过res.json直接返回json数据给客户端
  • 使用express-sessionconnect-redis、登陆中间件
  • 使用morgan来记录日志,根据配置决定将日志输出到控制台还是文件中

koa2

构建流程

  1. npm install koa-generator -g全局安装express命令安装工具
  2. Koa2 项目名
  3. npm install 安装组件
  4. npm i cross-env
  5. npm run dev启动项目(服务器)

相对于express和原生nodejs:

  • 直接通过ctx.query获取get传过来的参数,通过ctx.request.body获取 post传过来的参数
  • 通过ctx.body直接返回json数据给客户端
  • 通过async/await来实现中间件
  • 通过await next()来执行下一个中间件
  • 相比express,koa2在记录日志时要手动安装koa-morgan插件

中间件

一、express中间件
  • 其实中间件就是一个这样格式的函数,三个参数req, res, next
function loginCheck(req, res, next) {
    console.log('模拟登陆成功')
    next()
}
  • 可以通过app.use()app.get()app.post()注册中间件
  • 可以注册多个中间件,依次执行
  • 通过next()的执行一个一个的往下串联下一个中间件

实现原理思路:

  1. app.use用来注册中间件,先收集起来
  2. 遇到http请求,根据pathmethod判断触发哪些中间件
  3. 实现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()
}

二、koa2中间件
  • koa2中间件其实就是一个async函数,参数为(ctx, next)
app.use(async (ctx, next) => {
    await next();
    ctx.body = 'Hello World';
});

实现思路:

  • 也是使用app.use来注册中间件,先收集起来
  • 实现next机制,即上一个通过await next()触发下一个中间件
  • 不涉及methodpath的判断
<!--实现类似 靠中间件-->
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

node线上环境

PM2
  • 进程守护,系统奔溃自动重启restart,而不是说系统出错之后其他用户就无法使用了
  • 启动多进程,充分利用cpu 和内存
  • 自带日志记录功能

下载安装

cnpm i pm2 -g

配置命令

"prd": "cross-env NODE_ENV=production pm2 start app.js"

启动

npm run prd

常用命令

  • pm2 start … 启动进程
  • pm2 list: 可以查看pm2进程列表
  • pm2 restart appNme/id : 重启进程
  • pm2 stop appName/id : 停止
  • pm2 delete appName/id : 删除
  • pm2 info appName/id :查看基本信息
  • pm2 log appName/id :查看进程日志
  • pm2 monit appName/id:监控进程的cpu和内存信息

pm2配置文件

  1. 包括进程数量、日志文件目录等
  2. 修改pm2 启动命令,重启
  3. 访问 server,检查日志文件的内容(日志记录是否生效)
{
    "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" // 日志的时间戳
    }
}
多进程

为何使用多进程

  • 操作系统会限制一个进程的最大可用内存。因为按照软件设计拆分这种模式来说,如果一个进程做很多很多的事情,该进程万一奔溃,这可是天灾后果。因此需要分为多个进程,进程之间相互独立,提高了服务器稳定性
  • 因此多进程可以充分利用机器的内存,充分发挥多核CPU的优势(同时处理多个进程)

多进程和redis

  • 多进程之间的session无法共享
  • 采用共享redis 来解决

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Node-RED是一个基于浏览器的可视化编程工具,可用于连接各种硬件设备、API和在线服务。要从零开始学习Node-RED,首先需要安装Node.js和Node-RED,然后打开浏览器,输入localhost:1880即可访问Node-RED的编辑界面。 在Node-RED中,有三个核心概念:节点、流和消息。节点是可以执行特定任务的小工具,如读取传感器数据、发送电子邮件等。流是连接节点的线条,表示数据的流动路径。消息是节点之间传递的数据。通过拖拽节点到编辑界面,并通过线条连接起来,就可以构建自己的Node-RED流程了。 从入门实战,可以按照以下步骤进行: 1. 学习基本概念:理解节点、流和消息的概念,熟悉Node-RED的编辑界面和基本操作。 2. 探索节点功能:尝试使用各种节点,了解它们的功能和用法,如输入/输出节点、函数节点、控制节点等。 3. 创建简单流程:尝试创建简单的流程,如读取传感器数据并在控制台打印、发送HTTP请求等。 4. 进阶学习:探索更多节点和功能,学习如何处理消息、流程控制和错误处理等。 5. 实际应用:将Node-RED应用到实际项目中,如智能家居控制、物联网应用、自动化任务等,将所学知识付诸实践。 通过以上学习和实践,可以逐渐掌握Node-RED的基本用法和实战技巧,为将来的项目开发和工作应用做好准备。同时,Node-RED还有丰富的社区资源和插件支持,可以在实际应用中不断学习和提升。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值