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
- The router (The third layer: Returns different data according to different routes.)
- 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:
- Enable the following services (occupying different ports) : nodeJS Server service port 8000 (back-end interface), HTTP-server service port 8001 (front-end page)
- Listen on port 8080
- 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
- By visiting
http://localhost:8080/index.html
Can 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
npm install -g express -generator
Global Installation The Express command installs the toolExpress the project name
npm install
Installation of componentsnpm start
Start project (server)npm i nodemon cross-env
Write your own business logic:
- Create a routing file to process service logic for different routes
- The newly created routing file (e.g
blog.js
) to introduceapp.js
File, and useapp.use
Register our route
Relative to native NodeJS:
- Directly through
req.query
Get the argument passed by getreq.body
Gets the parameters passed by POST - through
res.json
Returns JSON data directly to the client - use
express-session
,connect-redis
Login middleware - use
morgan
To log to the console or to a file, depending on the configuration
koa2
The build process
npm install koa-generator -g
Global Installation The Express command installs the toolKoa2 project name
npm install
Installation of componentsnpm i cross-env
npm run dev
Start project (server)
As opposed to Express and native NodeJS:
express
thereq, res
.koa2
Put them both in CTX and manage them separatelyctx.request
和ctx.reponse
Make a direct visit- Directly through
ctx.query
Get the argument passed by getctx.request.body
Gets the parameters passed by POST - through
ctx.body
Returns JSON data directly to the client - through
async/await
To implement middleware - through
await next()
To execute the next middleware - Compared with the
express
, koA2 is manually installed during loggingkoa-morgan
The plug-in
The middleware
I. Express middleware
- In fact, middleware is a function in this format, three parameters
req, res, next
function loginCheck(req, res, next) {
console.log('Simulated landing successful')
next()
}
Copy the code
- Can be achieved by
app.use()
,app.get()
,app.post()
Registered middleware - Multiple middleware can be registered and executed sequentially
- through
next()
The execution of the next middleware cascades down one by one express
The middleware executes sequentially, one after the other, and usually willresponse
The response is written in the last middleware
Implementation principle:
app.use
Used to register middleware, collected first- encounter
http
Request, according topath
,method
Determine which middleware triggers - implementation
next()
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 one
async
Function, 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 used
app.use
To register middleware, collect it first - implementation
next
Mechanism, that is, the last one throughawait next()
Trigger the next middleware - Don’t involve
method
andpath
The 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 restart
restart
Instead 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
- Includes the number of processes and log file directories
- Modify the PM2 startup command and restart the PM2
- 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