• openresty开发


    nginx请求

    1. ngx.exec:nginx跳转;跳转到其他的location中执行。但仅限nginx内部的location。
    2. ngx.redirect:和nginx.exec相似,但支持外部跳转。
    3. ngx.location.capture_multi:并发请求;但仅限nginx内部的location,会缓冲整个请求到内存中。
      1. 发起请求时,get参数可以用table或者转义字符串,body不可
        ngx.location.capture(
        '/print_param',
        {
        method = ngx.HTTP_POST,
        args = {a = 1, b = '2&1'},
        body = ngx.encode_args({c = 3, d = '4&'})
        }

    4. http包中multi方法:概念上与ngx.location.capture_multi相似,但支持外部接口。

    读取请求参数:


      POST:

      1.ngx.req.read_body() -- 解析 body 参数之前一定要先读取 body

      ngx.req.get_post_args()

      2.get_body_data()

      这两种都可以获取post参数,第二种需要开启 lua_need_request_body on或先调用ngx.req.read_body() ;

      GET:
      ngx.req.get_uri_args()

     由于 Nginx 是为了解决负载均衡场景诞生的,所以它默认是不读取 body 的行为,会对 API Server 和 Web Application 场景造成一些影响。根据需要正确读取、丢弃 body 对 OpenResty 开发是至关重要的。

     ngx.say 或 ngx.print区别:

    ngx.say 会对输出响应体多输出一个  ,两者均为异步输出

    共享变量:

     ngx.ctx仅在当前请求内共享变量,每个请求,包括子请求,都有一份自己的 ngx.ctx 表,相对独立。(类似java threadLocal)

    ngx.var

     缓存:

      1.Lua shared dict

    lua_shared_dict my_cache 128m;

      2.Lua LRU cache

    shared.dict 使用的是共享内存,每次操作都是全局锁,如果高并发环境,不同 worker 之间容易引起竞争。所以单个 shared.dict 的体积不能过大。
    lrucache 是 worker 内使用的,由于 Nginx 是单进程方式存在,所以永远不会触发锁,效率上有优势,并且没有 shared.dict 的体积限制,内存上也更弹性,但不同 worker 之间数据不同享,同一缓存数据可能被冗余存储。

    IO密集型与CPU密集型:

    1.IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)

    2.计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等

    Nginx与Apache对于高并发处理上的区别。
    对于Apache,每个请求都会独占一个工作线程,当并发数到达几千时,就同时有几千的线程在处理请求了。这对于操作系统来说,占用的内存非常大,线程的上下文切换带来的cpu开销也很大,性能就难以上去,同时这些开销是完全没有意义的。
    对于Nginx来讲,一个进程只有一个主线程,通过异步非阻塞的事件处理机制,实现了循环处理多个准备好的事件,从而实现轻量级和高并发。

    为何推荐worker的个数为cpu的个数?
    因为更多的worker数,只会导致进程相互竞争cpu资源,从而带来不必要的上下文切换

    Nginx比较Apache:事件驱动适合于IO密集型服务,多进程或线程适合于CPU密集型服务

    1)Nginx更主要是作为反向代理,而非Web服务器使用。其网络模式是事件驱动(select、poll、epoll)。
    2)事件驱动的本质还是IO事件,应用程序在多个IO句柄间快速切换,实现所谓的异步IO。
    3)事件驱动服务器,最适合做的就是这种IO密集型工作,如反向代理,它在客户端与WEB服务器之间起一个数据中转作用,纯粹是IO操作,自身并不涉及到复杂计算。
    4)反向代理用事件驱动来做,显然更好,一个工作进程就可以run了,没有进程、线程管理的开销,CPU、内存消耗都小。
    5)当然,Nginx也可以是多进程 + 事件驱动的模式,几个进程跑libevent,不需要Apache那样动辄数百的进程数。
    6)Nginx处理静态文件效果也很好,那是因为静态文件本身也是磁盘IO操作,处理过程一样。至于说多少万的并发连接,这个毫无意义。

    我随手写个网络程序都能处理几万7)的并发,但如果大部分客户端阻塞在那里,就没什么价值。

    再看看Apache或者Resin这类应用服务器,之所以称他们为应用服务器,是因为他们真的要跑具体的业务应用,如科学计算、图形图像、数据库读写等。

    它们很可能是CPU密集型的服务,事件驱动并不合适。

    1)例如一个计算耗时2秒,那么这2秒就是完全阻塞的,什么event都没用。想想MySQL如果改成事件驱动会怎么样,一个大型的join或sort就会阻塞住所有客户端。
    2)这个时候多进程或线程就体现出优势,每个进程各干各的事,互不阻塞和干扰。当然,现代CPU越来越快,单个计算阻塞的时间可能很小,但只要有阻塞,

    事件编程就毫无优势。所以进程、线程这类技术,并不会消失,而是与事件机制相辅相成,长期存在。
    总结之,事件驱动适合于IO密集型服务,多进程或线程适合于CPU密集型服务,它们各有各的优势,并不存在谁取代谁的倾向


    如果在请求中,需要做一些跟返回终端无关的操作,比如日志推送、数据统计等。可以通过

    异步执行:

    ngx.eof()  
    它可以即时关闭连接,把数据返回给终端,后面的代码操作还会运行。
    需要注意的是,你不能任性的把阻塞的操作加入代码,即使在 ngx.eof()之后。 虽然已经返回了终端的请求,但是,Nginx 的 worker 还在被你占用。所以在 keep alive 的情况下,本次请求的总时间,会把上一次 eof() 之后的时间加上。 如果你加入了阻塞的代码,Nginx 的高并发就是空谈。

     定时器:

    timer ,每个 timer 都运行在独立的协程里,所以无论time执行多少次,counter变量每次都是1。

    如果要在 timer 的每次触发中共享变量,你有两个选择:

    1. 通过函数参数,把每个变量都传递一遍。
    2. 把要共享的变量当作模块变量。

    (当然也可以选择在 init_worker_by_lua* 里面、ngx.timer.* 外面定义真正的全局变量,不过不太推荐罢了)

    init_worker_by_lua_block {
        local delay = 5
        local handler
        handler = function()
            counter = counter or 0
            counter = counter + 1
            ngx.log(ngx.ERR, counter)
            local ok, err = ngx.timer.at(delay, handler)
            if not ok then
                ngx.log(ngx.ERR, "failed to create the timer: ", err)
                return
            end
        end
        local ok, err = ngx.timer.at(delay, handler)
        if not ok then
            ngx.log(ngx.ERR, "failed to create the timer: ", err)
            return
        end
    }
    限速
    1. limit_rate 限制响应速度
    2. limit_conn 限制连接数
    3. limit_req 限制请求数
    
    
    ngx.shared.DICT 的实现是采用红黑树实现,当申请的缓存被占用完后如果有新数据需要存储则采用 LRU 算法淘汰掉“多余”数据。
    使用长连接keepalive提升性能,连接redis等。
  • 相关阅读:
    SQL SERVER DBCC命令参考
    Sqlserver 死锁问题
    收集面试题目DB
    收集面试题目Net
    [转]Virtual PC 2007虚拟机上安装Ubuntu 8.10桌面版
    Tcl/tk基础-2
    【转】内存详解
    [转]C# P2P与NAT技术之二
    泛型跟KeyNotFoundException
    用InstallAware 9制作BDE安装程序
  • 原文地址:https://www.cnblogs.com/akaneblog/p/12563163.html
Copyright © 2020-2023  润新知