“This is the 21st day of my participation in the First Wen Challenge 2022.First challenge in 2022”

Nginx advanced applications

Application Scenarios:

This technology is not just used for AD caching, it’s just a cache that is often used for advertising!

AD cache loading and reading

For an application to more, every day there will be a lot of users to visit, then the most visited is the home page! And for the home page, high access, andPage data is not constantly changing! To take the strain off the server, make it oneStatic page for display!

Basic process:

  • Nginx has learned: can be implemented through the reverse proxy, gateway load balancing server! Users send requests, first through Nginx, through nginx proxy, load balancing, request corresponding gateway.. The module.
  • This is in the user login/common operation, request after nginx request, in nginx complete call redis data operation, direct return results! But niginx doesn’t have thatFeatures of a programming languageIf else, access database redis; It’s just a load balancer;So, you need to passLua embedded languageTo complete the
  • First access to nginx, we can use caching, first from the nginx local cache, to get the direct response
  • If not, access Redis again, we can retrieve data from Redis, return if there is, and cache it in nginx
  • If not, go back to mysql and get the data from mysql and store it in Redis.
  • We can use LUA scripts embedded in the program to perform these queries.

Lua

Brief introduction:

  • Lua is a lightweight scripting language written in standard C and open source C as the underlying language, writing things are fast!It is designed to be embedded in applications to provide flexible extension and customization capabilities for applications.

features

  • Lightweight: the use of C language and open source code form, compiled only one hundred K, can be very convenient embedded in other programs.

  • Extensible: ** Lua provides very easy to use extension interfaces and mechanisms ** built in a large number of developed, script files mysql redis…. (usually C or C++) provide these features and Lua can use them as if they were already built in.

  • Other features: Support for procedure-oriented programming and functional programming automatic memory management; A table implementation that provides only a generic type of array, hash, collection, and object can easily support some of the key mechanisms required by object-oriented programming, such as data abstraction, virtual functions, inheritance, and overloading, through closures and tables

    Application scenarios

Game development, standalone application scripts, Web application scripts, extensions and database plug-ins such as MySQL Proxy and MySQL WorkBench

The installation

Windows does not need to be installed, just need to configure the system environment variables: Environment variables are only for use in any other part of the system! Path: D:\WSMwork\lua(My installation path Lua53 or lua53 – I Can start Lua

An introduction to the Lua

Create the hello.lua file

Print:Print (" Print content!" );

  • To create a file, enterprint("hello");
  • Run CMD directly:

Execute command:Lua53 File name lua

Basic syntax of LUA

Introduction:

  • Lua has interactive programming and scripted programming:

  • Interactive programming is launching LuaEnter the syntax directly, and you can execute it directly.

  • Scripting requires writing scripts and then executing commands to execute the scripts. Scripting is generally used. (For example, write a hello.lua file, enter the contents of the file, and execute lua53 hell.lua.)

  • The syntax is the same, just the way it works… Here’s the basic syntax of Lua!

Scripted programmingCreate.lua file and execute...

Note:

hello.lua

-- single-line comment --[[multi-line comment]]--Copy the code

Define variables

As in Java, there are global and local variables:

  • Global whole file available!
  • localCan be used within specified methods!hello.lua
-- Global variable assignment
a=1
-- Local variable assignment
local b=2 
-.. Joining together
print(a.. b)print(a..':'..b)
Copy the code

The a=’ triple ‘character can be represented by single or double quotation marks, utF-8 can be garble, recommend file encoding ANSl If the variable is not initialized: then its value is nil which is different from null in Java.

case

The numerical operation still passes + - * /

Data types in Lua

  • Lua is a dynamically typed language. Variables do not need to be typed, only assigned values.
  • Values can be stored in variables and passed as arguments or returned as a result.
  • There are eight basic types in Lua:Nil, Boolean, number, String, userData, function, Thread, and table. Type (value) The type of the returned value
print(type("Hello world"))      --> string
print(type(10.4*3))             --> number contains double int
print(type(print))              --> function
print(type(type))               --> function
print(type(true))               --> boolean
print(type(nil))                --> nil
Copy the code

Process control

If statementOrcal-like stored procedures!

  • The if statement consists of a Boolean expression as a condition, followed by other statements.
 Conditional parentheses, optional: plus or minus
 if(Boolean expression)then  
    --[statement executed when Boolean expression is true --]
 end
Copy the code

if.. elseif… eles… End statement

  • If statements can be paired with elseif statements, else statements, and else statement blocks are executed if the if condition expression is false.

If - else

If (Boolean expression)then --[Boolean expression true to execute the block --] else --[Boolean expression false to execute the block --] endCopy the code

If - esleif - elseif - else - end

 local age =15
 ​
 if (age>=18) then
     print('Adult')
 elseif age<18 then
     print('minor')
 else
     print('unborn')    
 end 
Copy the code

Testing:

cycle

The while loop [And then we loop] do …. end

  • The while loop repeats the body of the loop when it judges that the condition is true.
 while(conditionstrueExecute)do
    print(' Execute loop content... ')end
Copy the code

The for loop

  • A for loop can execute a specified statement repeatedly, with a number of repetitions controlled within the for statement.
 for var=exp1,exp2,exp3 do  
     print(' Execute loop content... ')end 
 --[[var increments from exp1 to exp2 by exp3 and executes "body" once. Exp3 is optional. If not specified, default is 1.--
Copy the code

Repeat… Until the statement [Conditions met End]

  • Repeat… Until loop statements are different from for and while loops
  • Conditional statements for and while loops are judged at the start of the current loop executionRepeat will be executed once anyway, okayUntil the condition is trueEnd the loop!
 repeat
    print(' Execute loop content... ')until( trueExit loop)Copy the code

function

  • Functions can also be defined in Lua, similar to methods in Java.
 --[[function returns the maximum value of two values --]]
 function max(num1, num2)
    if (num1 > num2) then
       result = num1;
    else
       result = num2;
    end
 ​
    return result; 
 end
 Call function
 print("The maximum value between the two values is.max(10.4))
 print("The maximum value between the two values is.max(5.6))
Copy the code

Results after execution:

tabletable

  • Table is a Lua data structure that helps us create different data types, such as arrays, dictionaries, objects, etc.
 Alter table mytable = {}
 ​
 Mytable [1]= "Lua"
 ​
 -- Remove reference mytable = nil
Copy the code

Test the Demo

 table= {}table[0] ="Zhang SAN 1"
 table[1] ="Zhang SAN 2"
 table[2] ="Zhang SAN 3"
 ​
 -- Table is an object
 print(table)
 ​
 Get the value by subscript
 print(table[0])
 ​
 --table = nil to clear tables/objects
 table = nui
 print(table)
 print(table[0])
Copy the code

The module

The module definition

  • Since Lua 5.1, Lua has added a standard module management mechanism, which can put some common code in a file. Calling in the form of an API interface elsewhere facilitates code reuse and reduces code coupling.

Create a file calledmodule.lua

Don’t forget Chinese garble, file format set ASCII module.lua

 -- The file name is module.lua
 Define a module named module, the same as the file name!
 module = {}
  Define a constant
 module.constant = "This is a constant."
  Func1 -- Define a function module.func1
 function module.func1(a)
     print("This is a public function")
 end
 Define a local (private) method
 Therefore, the private function in the module cannot be accessed externally. It must be called through the public function in the module
 local function func2(a)
     print("This is a private function!")
 end
 Simulate calling private methods...
 function module.func3(a)
 func2()
 end
  
 return module
Copy the code
  • The structure of a module is the structure of a table,
  • So you can manipulate constants or functions in the module as if you were calling elements in the table

The require function

Require is used to introduce other modules, similar to Java classes that reference other classes. The module to be imported should be placed in a folder, which can be a subfile! Otherwise we can’t find it!

require("< module name >")
- or
require "< module name >"
Copy the code

OpenResty

Introduction to the

  • OpenResty® is a high-performance Web platform based on Nginx and Lua with a large number of excellent Lua libraries, third-party modules, and most of the dependencies internally integrated. It is used to easily build dynamic Web applications, Web services and dynamic gateways that can handle ultra-high concurrency and scalability.
  • To put it simply: OpenResty is Niginx, and Niginx integrates Lua with programming features developed by the OpenResty team

The system configuration

Directory structure:

D: WSMwork openresty-1.15.8.2-win64 lualib resty contains a lot of luAThe module

Configuration:

Configuring the lua library location: modifiedOpenresty - 1.15.8.2 - win64 \ conf \ nginx. Conffile

Most of the following operations are in: customConf file

lua.conf

Custom lua.conf

 # Give nginx 128 MB cache size! Used to store hot data (frequently used data!)
 lua_shared_dict my_cache 128m;
 ​
 # nginx service
 server {
     listen  9090;       # specify port 9090, default 80
     server_name _;
 ​
     # static template address set...
     set $template_location "/templates";
     set $template_root "D:/templates";      # Fill in the corresponding address...
     
     #nginx stream request path...
     location /mylua{
         default_type text/html;
         # pass content_by_lua_block{lua execution code} ngx.say(' is lua browser output method! ')
         content_by_lua_block{
             local age = 20
             if age>=18 then
                 ngx.say('> = 18');
             else 
                 ngx.say('< 18');
             end 
         }
     }
 }
Copy the code
  • This is a normal nginx configuration code:
  • content_by_lua_block{ } The lua execution is written here Nginx has the features of a programming language!OpenResty1.9.3.2 used to becontent_by_lua{ }throughnginx -vCheck the version number!
  • Ngx. say(‘ is lua’s browser output method! ‘) Just like Java's Out print stream!

Start/refresh nginx

Start the command

OpenResty directorycmd

  • nginx.exe No exception is successful!

restartThe refreshThe command

When modifying files, frequent calls to nginx.exe are started, open to carry out causing congestion! The correct way is to refresh and restart CMD in the OpenResty directory

  • nginx.exe -s reload

test

Bind () to 0.0.0.0:80 failed (10013: An attempt was made to access a……..)

  • The nginx.conf file also has a default port 80 boot.. May conflict with a port in the computer, direct change can! Or: Stop the processWindows! netstat -aon | findstr :8080 indicates a port.Tasklist | findstr searches "process"

OpenResty imports lua files:

Writing lua code in nginx configuration is not easy to write, you can directly write outside, call it!

 location /mylua2{
     default_type text/html;
     content_by_lua_file D:/WSMwork/myweb.lua;
 }
 #content_by_lua_file introduces the external lua file, ending with a semicolon;
Copy the code

content_by_lua_file

Import external.lua files

Define a file myweb.luaExternal file ~ Refresh the nginx

Initiate HTTP requests in openResty

  • Some scenarios require Nginx to forward requestsThis requires nginx to have the ability to make HTTP requests
  • The Nginx service makes a distinction between internal and external HTTP requests

To facilitate testing, launch a micro suit to view

The lua script

myweb.lua

 Set the encoding format!
 ngx.header.content_type="text/html; charset=utf8"
 ​
 Call a method in the NGX module that returns the request URL
 local uri_args = ngx.req.get_uri_args()
 Get request parameters!
 local zz = uri_args["zz"]
 -- get HTTP module, require();
 local http = require("resty.http")
 The HTTP module new() is an HTTPC object
 local httpc = http.new()
 ​
 -.. Splicing parameter WD
 local resp = httpc:request_uri("http://127.0.0.1:9002/info/hello/"..zz,{
     method = "GET".- get request;
     keepalive=false -- Ask anyway;
 })
 Return parameter result, print result!
 local val = resp.body
 ngx.say(val)
Copy the code

test

Note that the arguments here are in nginx,Request parameters for port 9090!

require(“resty.http”)

It’s this Lua module that loads requests, There are a lot of lua scripting modules in OpenResty…

Gets the POST request parameters

Very similar to get….

 ngx.req.read_body()                 Get the request URL
 local arg = ngx.req.get_post_args() Parameter set Map type!
 Declare several empty objects for storage
 id=nil      
 deptname=nil
 -- Loop parameter collection!
 for k,v in pairs(arg) do 
     -- Judge parameter,key parameter assignment!
     if k=="id" then
         id = v
     end
     if k=="deptname" then
         deptname = v
     end 
 end 
 -- Page output!
 ngx.say("deptname: ", deptname)
 ngx.say("id: ", id)
Copy the code

Post requests using postman:

Openresty uses the Redis module

  • Caching is often used in high-concurrency scenarios
  • Now the distributed cache that we often use redis is the best known and we need to introduce the redis module require “resty.redis”

The lua script

myweb.lua

 Define private methods
 local function close_redis(red)
     if not red then
         return
     end
     Release the connection (connection pooling implementation) in milliseconds
     local pool_max_idle_time = 10000 
     -- Connection pool size
     local pool_size = 100 
     local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
     local log = ngx_log
     if not ok then
         log(ngx_ERR, "set redis keepalive error : ", err)
     end
 end
 ​
 ​
 - connect the redis
 local redis = require('resty.redis')    -- Introducing modules
 local red = redis.new()
 red:set_timeout(1000)
 ​
 local ip = "127.0.0.1"
 local port = "6379" 
 -- local PWD = "ok"
 ​
 Connection test IP port is correct...
 ok, err = red:connect(ip,port)
 if not ok then
     ngx.say("failed to auth: ", err)
     return close_redis(red)
 end
 ​
 -- Password is correct without direct comment!
 --[[ ok, err = red:auth(pwd) if not ok then ngx.say("failed to auth: ", err) return close_redis(red) end ]]--
 Get the first redis library,redis total 16 libraries
 red:select('0')
 red:set("msg"."test ngx hello") --set stores a MSG key with the value test NGX hello
 -- get query by key... And handle exceptions
 local resp, err = red:get("msg")  
 if not resp then  
     ngx.say("get msg error : ", err)  
     return close_redis(red)  
 end
 Print off resource!
 ngx.say("msg : ", resp)
 close_redis(red)
Copy the code

Remember to start Redis!

Installation directory: Redis-server.exe

View all keys

Testing:

Direct gateway request!

Operate mysql in openresty

The database

Since want database operation, so make a database!mysql

The lua script

myweb.lua

 Create connection to mysql module
 local mysql = require "resty.mysql"
 -- connect to mysql;
 local db, err = mysql:new()
 ​
 if not db then
     return false    -- Not connected to close!
 end
 -- Timeout
 db:set_timeout(1000)    
 -- Set the connection information
 local ok, err, errno, sqlstate = db:connect{
     host = "127.0.0.1".--ip
     port = 3306.- port
     database = "book".-- Connected database
     user = "root".- the user
     password = "ok".- the password
     max_packet_size = 1024 * 1024   -- 1 MB in size
 }
 Verify that the connection is up
 if not ok then
     ngx.say("connect mysql failed")
     return false    -- Not connected to close
 end
 ​
 if db == false then
     ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
     return
 end
 ​
 ngx.say("---------- Query data ----------------"."<br/>")
 ​
 res, err, errcode, sqlstate =
     db:query("SELECT * FROM bookinfo")      In practice, the concatenation parameter.... may also be required
 ​
 -- No data, return... Abnormal!
 if not res then
     ngx.say("bad result: ", err, ":", errcode, ":", sqlstate, ".")
     return
 end
 Get the JSON module
 local cjson = require "cjson"
 --JSON translation, page output
 ngx.say("result: ", cjson.encode(res))
 ​
 -- If it is new...
 --[[-- if no result is returned, add exception message! Ngx. say("insert rows :", res.affected_rows,", id", if not res then ngx.say("insert rows :", res.affected_rows,", ID ", res.insert_id, "

") ]]
-- Copy the code

Results test:

Extension:

  • It is recommended to use nginx to reference external LuaConvenient troubleshooting, if there is an error, direct console run lua script can! Clear structure…