Nodejs后端架构基础知识和案例展示

Nodejs后端架构基础知识和案例展示,第1张

Nodejs后端架构基础知识和案例展示

入门笔记,大神请绕路!!!
简单的说 Node.js 就是运行在服务端的 Javascript。
Node.js 是一个基于Chrome Javascript 运行时建立的一个平台。
Node.js是一个事件驱动I/O服务端Javascript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。

NodeJS的优缺点
  • 优点:
    1.高并发(高并发的时候,会出现数据库连接数不够用的情况,网上还有对应解决方案,还未实践)
    2.适合I/O密集型应用
    3.事件驱动、非阻塞I/O、高效、轻量

解决数据库高并发,程序解决方案:
数据库高并发时,连接数不够。平台监听sql *** 作,如果状态是ready,就回调执行sql *** 作。相当于将sql *** 作也做异步回调处理,每次sql *** 作都是在上次 *** 作ready后,再执行,强制串行执行sql *** 作。这样就减轻数据库压力。但是也可能导致整个应用变慢。

var proxy = new EventProxy();
var status = "ready";
var select = function(callback){
    proxy.once("selected",callback);
    if(status == "ready"){
        status = "pending";
        db.select("SQL", function(results){
            proxy.emit("selected",results);
            status = "ready";
        });
    }
  • 缺点:
    1.不适合CPU密集型应用;
    CPU密集型应用给Node带来的挑战主要是:由于Javascript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
    解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
    2.只支持单核CPU,不能充分利用CPU(可以利用多进程利用cpu的,cluster就可以让你做到nodejs将电脑多核利用起来)解决方案:
    (1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
    (2)开多个进程监听同一个端口,使用cluster模块;
应用场景

1. RESTful API
这是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。它本质上只是从某个数据库中查找 一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。

2. 统一Web应用的UI层
目前MVC的架构,在某种意义上来说,Web开发有两个UI层,一个是在浏览器里面我们最终看到的,另一个在server端,负责生成和拼接页面

不讨论这种架构是好是坏,但是有另外一种实践,面向服务的架构,更好的做前后端的依赖分离。如果所有的关键业务逻辑都封装成REST调用,就意味着在上层 只需要考虑如何用这些REST接口构建具体的应用。那些后端程序员们根本不 *** 心具体数据是如何从一个页面传递到另一个页面的,他们也不用管用户数据更新是 通过Ajax异步获取的还是通过刷新页面。

3. 大量Ajax请求的应用

例如个性化应用,每个用户看到的页面都不一样,缓存失效,需要在页面加载的时候发起Ajax请求,NodeJS能响应大量的并发请求。总而言之,NodeJS适合运用在高并发、I/O密集、少量业务逻辑的场景。

演示一:Hello World!

脚本模式
以下是我们的第一个Nodejs程序:

console.log("Hello World");

保存该文件,文件名为 helloworld.js, 并通过 node命令来执行:node helloworld.js。程序执行后,正常的话,就会在终端输出 Hello World。

image.png

交互模式
打开终端,键入node进入命令交互模式,可以输入一条代码语句后立即执行并显示结果,例如:

$ node
> console.log('Hello World!');
Hello World!
image 演示二:nodejs基于http插件,监听接口,返回数据

1、新建app.js文件,然后并执行执行node app.js。
代码如下:

var http = require('http');
var server = http.createServer(function (req, res) {
    var body = '';
    req.on('data', function(data) {      // 接收客户端发送过来的数据, 也就是 xmlHttp.send(value);
        body += data;
    });

    req.on('end', function() {
        res.writeHeader(200, {
            'Content-Type': 'text/plain',
            'Access-Control-Allow-Origin': '*'    //解决跨域问题
        });
        res.write("hello:" + body);
        res.end();
    })
});
server.listen(3000, function () {
    console.log('server start at localhost:3000');
});

2、找个引入jquery的页面,执行post请求:

$.ajax({
url:"http://localhost:3000",
data:"我是快递小哥,请开开门",
type:"post",
success:function(d){console.log("success",d)},
error:function(d){console.log("error",d)}
})

执行请求,返回hello:我是快递小哥,请开开门

image.png

这个例子中,nodejs充当后台,app.js中实现了http://loadlhost:3000接口,返回了前端提交的内容。

演示三:nodejs基于express插件,监听接口,返回数据

1、新建service.js文件,然后执行执行node service.js。
代码如下:

//demo
const express = require('express');
const app = express();

//设置允许跨域访问该服务.
app.all('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  //Access-Control-Allow-Headers ,可根据浏览器的F12查看,把对应的粘贴在这里就行
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Methods', '*');
  res.header('Content-Type', 'application/json;charset=utf-8');
  next();
});

app.post('/hello', function (req, res) {
  res.json({title:"你好"});
  
});

const server = app.listen(8082, function () {
  console.log('Express app server listening on port %d', server.address().port);
});

2、找个引入jquery的页面,执行post请求:

$.ajax({
url:"http://localhost:8082/hello",
type:"post",
success:function(d){console.log("success",d)},
error:function(d){console.log("error",d)}
})

返回数据:

image.png 演示四:nodejs+express+mysql搭建后端环境

引用:http://www.cnblogs.com/ssqqhh/p/6289690.html1、创建数据库
创建名为nodejs的数据库,新建一张users表,采用utf8编码。表结构和数据如下:

image.png 2、安装express
npm i express -g//安装express
npm i express-generator -g//安装命令行工具
express --version//检测express是否安装成功

3、创建express项目
执行express express-demo,新建express项目,文件目录说明:

app.js//启动文件,或者说入口文件。新的页面以及页面相应的路由需要在这里配置;
package.json//存储着工程的信息及模块依赖,当在 dependencies 中添加依赖的模块时,运行 npm install,npm //会检查当前目录下的 package.json,并自动安装所有指定的模块
node_modules//存放 package.json 中安装的模块,当你在 package.json 添加依赖的模块并安装后,存放在这个文件夹下
public//存放 image、css、js 等文件
routes//存放路由文件
views//存放视图文件或者说模版文件
bin//存放可执行文件

4、运行express项目

cd express-demo//进入项目
npm i//安装依赖文件
npm start//启动项目

启动成功,空荡荡的页面中就出现下面内容

image.png 5、写项目代码
需要创建以下文件: modelconfig.js:数据库配置
module.exports = {
    mysql: {
        host: 'localhost',
        user: 'root',
        password: '123123',
        database: 'nodejs',
        port: 3306
    }
};

viewslogin.jade:登录页面

doctype html
html
  head
    title
    link(href='/stylesheets/style.css', rel='stylesheet')
    link(href='/bootstrap-3.3.7/css/bootstrap.min.css', rel='stylesheet')
    script(src='/javascripts/jquery.min.js')
    script(src='/bootstrap-3.3.7/js/bootstrap.min.js')
  body(style='background: #dcd9da')
    // h1= title
    .container
      .row
        .col-md-4.col-md-offset-4
          .panel.panel-default(style='margin-top: 100px')
            .panel-heading(style='background: #0d6aad')
              h4(align='center', style='color: #ffffff;')
                | express-jade-bootstrap-mysql-demo
            .panel-body(style='background: #e0e1ea')
              .form-group
                .input-group
                  span.input-group-addon 账号
                  input#username.form-control(type='text', placeholder='请输入账号')
              .form-group
                .input-group
                  span.input-group-addon 密码
                  input#password.form-control(type='password', placeholder='请输入密码')
              .form-group
                .col-lg-offset-7
                  | 没有账号?
                  a(href='/register') 注册
              .form-group
                button#login.btn.btn-success.btn-block(type='button')
                  | 登录
              #popup.alert.alert-warning
                a#close.close(href='#') ×
                div(align='center')
                  strong#popup-content(style='color: #b12e30;')
    script(type='text/javascript').
      $(document).ready(function () {
        var username = $("#username");
        var password = $("#password");
        var login = $("#login");
        var popup = $("#popup");
        var popupContent = $("#popup-content");
        var close = $("#close");
        popup.hide();
        close.click(function () {
          popup.hide();
        });
        login.click(function () {
          if (username.val() == "" || password.val() == "") {
            popup.show();
            popupContent.html("账号或密码不能为空!");
          } else {
            $.ajax({
                      url: "/login/userLogin",
                      data: {
                        username: $("#username").val(),
                        password: $("#password").val()
                      },
                      type: "POST",
                      timeout: 36000,
                      dataType: "text",
                      success: function (data, textStatus) {
                        //alert(data);
                        var dataJson = eval("(" + data + ")");
                        if (dataJson.code == 200) {
                          alert("登录成功");
                          window.location.href = "/";
                        } else if (dataJson.code == 300) {
                          popup.show();
                          popupContent.html("账号不存在,请重新输入!");
                        } else if (dataJson.code == 400) {
                          popup.show();
                          popupContent.html("密码有误,请重新输入!");
                        } else {
                          popup.show();
                          popupContent.html("登录出错!");
                        }
                      },
                      error: function (XMLHttpRequest, textStatus, errorThrown) {
                        alert("error:" + textStatus);
                      }
                    }
            );
          }
        })
        ;
      })
      ;

routeslogin.js:登录接口逻辑

var express = require('express');
var router = express.Router();
// 实现与MySQL交互
var mysql = require('mysql');
var config = require('../model/config');
// 使用连接池,提升性能
var pool = mysql.createPool(config.mysql);

router.get('/', function (req, res, next) {
    res.render('login', { title: 'login' });
});
router.post('/userLogin', function (req, res, next) {
    var username = req.body.username;//获取前台请求的参数
    var password = req.body.password;
    pool.getConnection(function (err, connection) {
        //先判断该账号是否存在
        var $sql = "select * from users where username=?";
        connection.query($sql, [username], function (err, result) {
            var resultJson = result;
            console.log(resultJson.length);
            if (resultJson.length === 0) {
                result = {
                    code: 300,
                    msg: '该账号不存在'
                };
                res.json(result);
                connection.release();
            } else {  //账号存在,可以登录,进行密码判断
                var $sql1 = "select password from users where username=?";
                connection.query($sql1, [username], function (err, result) {
                    var temp = result[0].password;  //取得数据库查询字段值
                    console.log(temp);
                    if (temp == password) {
                        result = {
                            code: 200,
                            msg: '密码正确'
                        };
                    } else {
                        result = {
                            code: 400,
                            msg: '密码错误'
                        };
                    }
                    res.json(result); // 以json形式,把 *** 作结果返回给前台页面
                    connection.release();// 释放连接
                });
            }
        });
    });
});
module.exports = router;

viewsregister.jade:注册页面

doctype html
html
  head
    title
    link(href='/bootstrap-3.3.7/css/bootstrap.min.css', rel='stylesheet')
    script(src='/javascripts/jquery.min.js')
    script(src='/bootstrap-3.3.7/js/bootstrap.min.js')
  body(style='background: #dcd9da')
    nav.collapse.navbar-collapse.navbar-inverse
      .navbar-header
        a.navbar-brand express-jade-bootstrap-mysql-demo
      ul.nav.navbar-nav.navbar-right
        li(style='margin-right: 20px')
          a(href='/login')
            span.glyphicon.glyphicon-log-in
            |  登录
    .container
      .row
        .col-md-4.col-md-offset-4
          .panel.panel-default(style='margin-top: 40px')
            .panel-heading(style='background: #0d6aad')
              h3(align='center', style='color: #ffffff;')
                | 账号注册
            .panel-body(style='background: #e0e1ea')
              .form-group
                .input-group
                  span.input-group-addon   账   号  
                  input#username.form-control(type='text', placeholder='请输入账号')
              .form-group
                .input-group
                  span.input-group-addon   密   码  
                  input#password.form-control(type='password', placeholder='请输入密码')
              .form-group
                .input-group
                  span.input-group-addon 确认密码
                  input#password1.form-control(type='password', placeholder='请再次输入密码')
              .form-group
                .input-group
                  span.input-group-addon   姓   名  
                  input#name.form-control(type='text', placeholder='请输入姓名')
              .form-group
                button#register.btn.btn-success.btn-block(type='button')
                  | 注册
              #popup.alert.alert-warning
                a#close.close(href='#') ×
                div(align='center')
                  strong#popup-content(style='color: #b12e30;')
    script(type='text/javascript').
      $(document).ready(function () {
        var username = $("#username");
        var password = $("#password");
        var password1 = $("#password1");
        var name = $("#name");
        var register = $("#register");
        var popup = $("#popup");
        var popupContent = $("#popup-content");
        var close = $("#close");
        popup.hide();
        close.click(function () {
          popup.hide();
        });
        register.click(function () {
          if (username.val() == "" || password.val() == "" || password1.val() == "" || name.val() == "") {
            popup.show();
            popupContent.html("注册信息不能为空!");
          } else if (password.val() !== password1.val()) {
            popup.show();
            popupContent.html("两次输入的密码不一样!");
          } else {
            //访问服务器,将注册信息写入数据库
            $.ajax({
              url: "/register/userRegister",
              data: {
                username: $("#username").val(),
                password: $("#password").val(),
                name: $("#name").val()
              },
              type: "POST",
              timeout: 36000,
              dataType: "text",
              success: function (data, textStatus) {
                var dataJson = eval("(" + data + ")");
                if (dataJson.code == 200) {
                  alert("注册成功");
                  window.location.href = "/login";
                } else if (dataJson.code == 300) {
                  popup.show();
                  popupContent.html("该账号已存在!");
                } else if (dataJson.code == 400) {
                  popup.show();
                  popupContent.html("注册失败,请重新注册!");
                } else {
                  popup.show();
                  popupContent.html("注册出错!");
                }
              },
              error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("error:" + textStatus);
              }
            });
          }
        });
      });

routesregister.js:注册接口逻辑

var express = require('express');
var router = express.Router();
// 实现与MySQL交互
var mysql = require('mysql');
var config = require('../model/config');
// 使用连接池,提升性能
var pool = mysql.createPool(config.mysql);

router.get('/', function (req, res, next) {
    res.render('register', { title: 'register' });
});
router.post('/userRegister', function (req, res, next) {
    var username = req.body.username;
    var password = req.body.password;
    var name = req.body.name; //获取前台请求的参数
    pool.getConnection(function (err, connection) {
        //先判断该账号是否存在
        var $sql = "select * from users where username=?";
        connection.query($sql, [username], function (err, result) {
            var resultJson = result;
            console.log(resultJson.length);
            if (resultJson.length !== 0) {
                result = {
                    code: 300,
                    msg: '该账号已存在'
                };
                res.json(result);
                connection.release();
            } else {  //账号不存在,可以注册账号
                // 建立连接,向表中插入值  数据库表名为user-info会出错
                var $sql1 = "INSERT INTO users(id, username, password, name) VALUES(0,?,?,?)";
                connection.query($sql1, [username, password, name], function (err, result) {
                    console.log(result);
                    if (result) {
                        result = {
                            code: 200,
                            msg: '注册成功'
                        };
                    } else {
                        result = {
                            code: 400,
                            msg: '注册失败'
                        };
                    }
                    res.json(result); // 以json形式,把 *** 作结果返回给前台页面
                    connection.release();// 释放连接
                });
            }
        });
    });
});
module.exports = router;

app.js:修改代码

...
var login = require("./routes/login");
var register = require("./routes/register");
...
app.use('/login', login);
app.use('/register', register);
...

jquery.min.js:引入jquery,放到public文件夹bootstrap:引入bootstrap,放到public文件夹

准备好以上代码后,执行npm start命令启动项目,打开登录页面:http://localhost:3000/login,注册页面:http://localhost:3000/register

登陆成功 注册成功

参考: NodeJs+Express+SqlServer简易后台API服务搭建

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5691138.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存