The construction process (in the order of creation) is introduced layer by layer

Four levels of abstraction for system architecture design:

  • Layer 1: www.js [Start Server]
  • Layer 2: app.js [Communication Settings layer]
  • Layer 3: Router.js [Business Logic layer]
  • Layer 4: Controller.js [data layer]

Overall structure:

  • Bin /www.js (layer 1) : Basic process configuration for Node to build services, independent of services. Import file configured in package
  • App.js (Layer 2)
  • src
    • The router (The third layer: Returns different data according to different routes.)
      • Blog.js: Blog CRUD interface
      • User.js: user-specific interface
    • Control (Layer 4: returns data to the routing side, only cares about the data and processing, usually with the database side)
    • Model (Data model: data format returned on success, failure, etc.)
    • Configuration of the conf:
      • Db.js: Obtain the environment parameters to configure the database, and use different databases according to the development environment and online environment
    • db
      • Mysql.js: basic operation on database (connection creation closed, no business logic involved)
      • Redis. js: encapsulates redis set and get operations
    • Utils: tool
      • Log.js: a tool for writing logs
  • Logs: log
    • Access. log: stores access logs
    • Event. log: Stores some custom content
    • Error. log: Stores error content

record

The session and Redis

I. Insufficient Session:

  • Session is stored in the memory of the nodeJS process
  • The process memory is limited. If the session is too large, the process will burst
  • The memory between processes is independent from each other and cannot be shared. Therefore, sessions cannot be shared between multiple processes

Solution: Store sessions in Redis

  • Redis is another service that has nothing to do with the Web Server nodeJS process
  • Redis is similar to a database. It is also a data warehouse for storing data.
  • However, the data of common databases is stored on hard disks, and the access speed is slow
  • Data on Redis is stored in memory, which is fast to access but expensive

Why is session storage suitable for Redis

  • Session access is frequent and has high performance requirements
  • Session does not take into account breakpoint loss of data (memory damage), because it is not possible to log in again
  • The amount of session data is not very large and generally only stores users’ personal information (compared to data stored in MySQL).

3. Start redis service:

Open a CMD window and run the CD command to switch to the redis directory

redis-server.exe redis.windows.conf
Copy the code

Interface and front-end integration

  • The login function relies on cookies and must be coordinated with a browser (postman cannot)
  • Cookies are not shared across domains. The front-end and server must be in the same domain
  • Therefore, you need to use Nginx as a proxy, so that the front and back end of the domain

Nginx is introduced

  • High performance Web server, open source free
  • Generally used for static service (CDN) and load balancing
  • The reverse proxy

How to configure a reverse proxy:

  1. Enable the following services (occupying different ports) : nodeJS Server service port 8000 (back-end interface), HTTP-server service port 8001 (front-end page)
  2. Listen on port 8080
  3. Reverse proxy Configuration

Nginx. conf configuration file:

location / {
    If the root directory is http://localhost:8080, proxy to port 8001
	proxy_pass http://localhost:8001;
}

location /api/ {
    If it is an access interface, proxy to port 8000
	proxy_pass http://localhost:8000;
    proxy_set_header Host $host;
}

Copy the code
  1. By visitinghttp://localhost:8080/index.htmlCan be

Ps:

  • Start nginx service:start nginx
  • Enable the HTTP-server service:http-server -p8001
  • To start the nodeJs server service:npm run dev

Nginx command

  • Start nginx: starts the nginx service
  • Nginx -t: tests whether the syntax of the nginx.conf file is correct

Express to build

The build process

  1. npm install -g express -generatorGlobal Installation The Express command installs the tool
  2. Express the project name
  3. npm installInstallation of components
  4. npm startStart project (server)
  5. npm i nodemon cross-env

Write your own business logic:

  1. Create a routing file to process service logic for different routes
  2. The newly created routing file (e.gblog.js) to introduceapp.jsFile, and useapp.useRegister our route

Relative to native NodeJS:

  • Directly throughreq.queryGet the argument passed by getreq.bodyGets the parameters passed by POST
  • throughres.jsonReturns JSON data directly to the client
  • useexpress-session,connect-redisLogin middleware
  • usemorganTo log to the console or to a file, depending on the configuration

koa2

The build process

  1. npm install koa-generator -gGlobal Installation The Express command installs the tool
  2. Koa2 project name
  3. npm installInstallation of components
  4. npm i cross-env
  5. npm run devStart project (server)

As opposed to Express and native NodeJS:

  • expressthereq, res.koa2Put them both in CTX and manage them separatelyctx.requestctx.reponseMake a direct visit
  • Directly throughctx.queryGet the argument passed by getctx.request.bodyGets the parameters passed by POST
  • throughctx.bodyReturns JSON data directly to the client
  • throughasync/awaitTo implement middleware
  • throughawait next()To execute the next middleware
  • Compared with theexpress, koA2 is manually installed during loggingkoa-morganThe plug-in

The middleware

I. Express middleware

  • In fact, middleware is a function in this format, three parametersreq, res, next
function loginCheck(req, res, next) {
    console.log('Simulated landing successful')
    next()
}
Copy the code
  • Can be achieved byapp.use(),app.get(),app.post()Registered middleware
  • Multiple middleware can be registered and executed sequentially
  • throughnext()The execution of the next middleware cascades down one by one
  • expressThe middleware executes sequentially, one after the other, and usually willresponseThe response is written in the last middleware

Implementation principle:

  1. app.useUsed to register middleware, collected first
  2. encounterhttpRequest, according topath,methodDetermine which middleware triggers
  3. implementationnext()Mechanism, that is, the last one throughnext()Trigger the next
// Implement middleware like express const HTTP = require('http')
const slice = Array.prototype.slice

class LikeExpress {
    constructor() {/ / collect storage middleware list enclosing routes = {all: [], / / app. Use (...). get: [], // app.get(...) post: [] // app.post(...) } } register(path) { const info = {}if (typeof path === 'string'Stack info.stack = slice.call(arguments, 1)}else {
            info.path = '/'Stack info.stack = slice.call(arguments, 0)}returnInfo} // Middleware registration and collectionuse() {
        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)} // Middleware match(method, url) {let stack = []
        if (url === '/favicon.ico') {
            returnStack} // Get routeslet 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'And routeInfo. Path = = ='/'
                // url === '/api/get-cookie'And routeInfo. Path = = ='/api'
                // url === '/api/get-cookie'And routeInfo. Path = = ='/api/get-cookie'
                stack = stack.concat(routeInfo.stack)
            }
        })
        return// Handle (req, res, stack) {const next = () => {const middleware = stack.shift()if(Middleware) {// Execute middleware functions (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(... Module.exports = () => {// exports = () => {return new LikeExpress()
}

Copy the code

Two, KOA2 middleware

  • Koa2 middleware is oneasyncFunction, with arguments of(ctx, next)
  • The middleware execution order is the onion ring model
app.use(async (ctx, next) => {
    await next();
    ctx.body = 'Hello World';
});
Copy the code

Implementation idea:

  • Is also usedapp.useTo register middleware, collect it first
  • implementationnextMechanism, that is, the last one throughawait next()Trigger the next middleware
  • Don’t involvemethodandpathThe judgment of the
<! --> const HTTP = require('http') // Combined middlewarefunction 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)
            returnthis.handleRequest(ctx, fn) } } listen(... args) { const server = http.createServer(this.callback()) server.listen(... args) } } module.exports = LikeKoa2Copy the code

Node Online Environment

PM2

  • Daemon process, system crash automatic restartrestartInstead of saying that the system fails and other users are unable to use it
  • Start multiple processes to make full use of CPU and memory
  • Provides the log recording function

Download and install

cnpm i pm2 -g
Copy the code

Configuration commands

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

Start the

npm run prd
Copy the code

Common commands

  • pm2 start … Start the process
  • Pm2 list: You can view the PM2 process list
  • Pm2 restart appNme/id: restarts a process
  • Pm2 stop appName/id: Stops
  • Pm2 delete appName/ ID: Deletes a file
  • Pm2 info appName/ ID: View basic information
  • Pm2 log appName/ ID: Displays process logs
  • Pm2 monit appName/ ID: monitors the CPU and memory information of processes

Pm2 configuration file

  1. Includes the number of processes and log file directories
  2. Modify the PM2 startup command and restart the PM2
  3. Access the server and check the contents of the log file (whether the log records are valid)
{
    "apps": {
        "name": "pm2-test-server"// Process name"script": "app.js"// Use the frame'bin/www'
        "watch": true, // Listen for file changes, whether to restart automatically"ignore_watch": [// which files do not need to be restarted"node_modules"."logs"]."instances": 4, // Number of processes, here"error_file": "logs/err.log"// Error log location"out_file": "logs/out.log"// The original console customization printed on the console is stored in a file"log_date_format": "YYYY-MM-DD HH:mm:ss"// Log timestamp}}Copy the code

Multiple processes

Why multiple processes

  • The operating system limits the maximum available memory for a process. If a process does too many things and crashes, it’s an act of God. Therefore, multiple processes need to be divided into independent processes to improve server stability
  • Therefore, multiple processes can make full use of the machine’s memory and take full advantage of the multi-core CPU (processing multiple processes at the same time).

Multiprocess and Redis

  • The session between multiple processes cannot be shared
  • Use shared Redis to solve