nginx技术(1)nginx高并发介绍和nginx安装,


nginx介绍和安装


一,nginx为什么支持高并发?epoll和select的区别

开发高性能网络程序时,windows开发者们言必称iocp,linux开发者们则言必称epoll。nginx就是用这种方式编写的。大家都明白epoll是一种IO多路复用技术,可以非常高效的处理数以百万计的socket句柄,比起以前的select和poll效率高大发了。我们用起epoll来都感觉挺爽,确实快,那么,它到底为什么可以高速处理这么多并发连接呢?

先简单回顾下如何使用C库封装的3个epoll系统调用吧。

[cpp]viewplaincopy
  1. intepoll_create(intsize);

  2. intepoll_ctl(intepfd,intop,intfd,structepoll_event*event);

    intepoll_wait(intepfd,structepoll_event*events,intmaxevents,inttimeout)


使用起来很清晰,首先要调用epoll_create建立一个epoll对象。参数size是内核保证能够正确处理的最大句柄数,多于这个最大数时内核可不保证效果。

epoll_ctl可以操作上面建立的epoll,例如,将刚建立的socket加入到epoll中让其监控,或者把epoll正在监控的某个socket句柄移出epoll,不再监控它等等。

epoll_wait在调用时,在给定的timeout时间内,当在监控的所有句柄中有事件发生时,就返回用户态的进程。

从上面的调用方式就可以看到epoll比select/poll的优越之处:因为后者每次调用时都要传递你所要监控的所有socket给select/poll系统调用,这意味着需要将用户态的socket列表copy到内核态,如果以万计的句柄会导致每次都要copy几十几百KB的内存到内核态,非常低效。而我们调用epoll_wait时就相当于以往调用select/poll,但是这时却不用传递socket句柄给内核,因为内核已经在epoll_ctl中拿到了要监控的句柄列表。
由于在执行epoll_create和epoll_ctrl时,已经把用户态的信息保存到内核态了
,所以之后即使反复地调用epoll_wait,也不会重复地拷贝参数,扫描文件描述符,
反复地把当前进程放入/放出等待队列。这样就避免了以上的三个缺点。

所以,实际上在你调用epoll_create后,内核就已经在内核态开始准备帮你存储要监控的句柄了,每次调用epoll_ctl只是在往内核的数据结构里塞入新的socket句柄。

在内核里,一切皆文件。所以,epoll向内核注册了一个文件系统,用于存储上述的被监控socket。当你调用epoll_create时,就会在这个虚拟的epoll文件系统里创建一个file结点。当然这个file不是普通文件,它只服务于epoll。

epoll在被内核初始化时(操作系统启动),同时会开辟出epoll自己的内核高速cache区,用于安置每一个我们想监控的socket,这些socket会以红黑树的形式保存在内核cache里,以支持快速的查找、插入、删除。这个内核高速cache区,就是建立连续的物理内存页,然后在之上建立slab层,简单的说,就是物理上分配好你想要的size的内存对象,每次使用时都是使用空闲的已分配好的对象。

[cpp]viewplaincopy
  1. staticint__initeventpoll_init(void)

  2. {

  3. ......

  4. /*Allocatesslabcacheusedtoallocate"structepitem"items*/

  5. epi_cache=kmem_cache_create("eventpoll_epi",sizeof(structepitem),

  6. 0,SLAB_HWCACHE_ALIGN|EPI_SLAB_DEBUG|SLAB_PANIC,

  7. NULL,NULL);

  8. /*Allocatesslabcacheusedtoallocate"structeppoll_entry"*/

  9. pwq_cache=kmem_cache_create("eventpoll_pwq",

  10. sizeof(structeppoll_entry),0,

  11. EPI_SLAB_DEBUG|SLAB_PANIC,NULL,NULL);

  12. ......


epoll的高效就在于,当我们调用epoll_ctl往里塞入百万个句柄时,epoll_wait仍然可以飞快的返回,并有效的将发生事件的句柄给我们用户。这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。

而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已,如何能不高效?!

那么,这个准备就绪list链表是怎么维护的呢?当我们执行epoll_ctl时,除了把socket放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。所以,当一个socket上有数据到了,内核在把网卡上的数据copy到内核中后就来把socket插入到准备就绪链表里了。

如此,一颗红黑树,一张准备就绪句柄链表,少量的内核cache,就帮我们解决了大并发下的socket处理问题。执行epoll_create时,创建了红黑树和就绪链表,执行epoll_ctl时,如果增加socket句柄,则检查在红黑树中是否存在,存在立即返回,不存在则添加到树干上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据。执行epoll_wait时立刻返回准备就绪链表里的数据即可。

最后看看epoll独有的两种模式LT和ET。无论是LT和ET模式,都适用于以上所说的流程。区别是,LT模式下,只要一个句柄上的事件一次没有处理完,会在以后调用epoll_wait时次次返回这个句柄,而ET模式仅在第一次返回。

这件事怎么做到的呢?当一个socket句柄上有事件时,内核会把该句柄插入上面所说的准备就绪list链表,这时我们调用epoll_wait,会把准备就绪的socket拷贝到用户态内存,然后清空准备就绪list链表,最后,epoll_wait干了件事,就是检查这些socket,如果不是ET模式(就是LT模式的句柄了),并且这些socket上确实有未处理的事件时,又把该句柄放回到刚刚清空的准备就绪链表了。所以,非ET的句柄,只要它上面还有事件,epoll_wait每次都会返回。而ET模式的句柄,除非有新中断到,即使socket上的事件没有处理完,也是不会次次从epoll_wait返回的。



二,编译安装nginx

1,nginx的编译安装需要的包

1 2 3 4 yum  -y  install  gcc   gcc-c++   autoconf    automake编译工具 yum  install -y zlib  zlib-devel    nginx提供gzip的模块,需要zlib库的支持 yum  install -y  openssl  openssl-devel     nginx提供ssl的功能 yum  install  pcre-devel   支持nginx的地址重写rewrite的功能,

2,编译参数

--prefix=<path>Nginx安装路径。如果没有指定,默认为/usr/local/nginx。 --sbin-path=<path>-Nginx可执行文件安装路径。只能安装时指定,如果没有指定,默认为<prefix>/sbin/nginx。 --conf-path=<path>-在没有给定-c选项下默认的nginx.conf的路径。如果没有指定,默认为<prefix>/conf/nginx.conf。 --pid-path=<path>-在nginx.conf中没有指定pid指令的情况下,默认的nginx.pid的路径。如果没有指定,默认为<prefix>/logs/nginx.pid。 --lock-path=<path>-nginx.lock文件的路径。 --error-log-path=<path>-在nginx.conf中没有指定error_log指令的情况下,默认的错误日志的路径。如果没有指定,默认为<prefix>/logs/error.log。 --http-log-path=<path>-在nginx.conf中没有指定access_log指令的情况下,默认的访问日志的路径。如果没有指定,默认为<prefix>/logs/access.log。 --user=<user>-在nginx.conf中没有指定user指令的情况下,默认的nginx使用的用户。如果没有指定,默认为nobody。 --group=<group>-在nginx.conf中没有指定user指令的情况下,默认的nginx使用的组。如果没有指定,默认为nobody。 --builddir=DIR-指定编译的目录 --with-rtsig_module-启用rtsig模块 --with-select_module --without-select_module //允许或不允许开启SELECT模式,如果configure没有找到更合适的模式,比如:kqueue(sunos),epoll(linuxkenel2.6+),rtsig(实时信号)或者/dev/poll(一种类似select的模式,底层实现与SELECT基本相同,都是采用轮训方法)SELECT模式将是默认安装模式 --with-poll_module --without-poll_module --with-http_ssl_module //开启HTTPSSL模块,使NGINX可以支持HTTPS请求。这个模块需要已经安装了OPENSSL,在DEBIAN上是libssl --with-http_realip_module-启用ngx_http_realip_module --with-http_addition_module-启用ngx_http_addition_module --with-http_sub_module-启用ngx_http_sub_module --with-http_dav_module-启用ngx_http_dav_module --with-http_flv_module-启用ngx_http_flv_module --with-http_stub_status_module-启用"serverstatus"页 --without-http_charset_module-禁用ngx_http_charset_module --without-http_gzip_module-禁用ngx_http_gzip_module.如果启用,需要zlib。 --without-http_ssi_module-禁用ngx_http_ssi_module --without-http_userid_module-禁用ngx_http_userid_module --without-http_access_module-禁用ngx_http_access_module --without-http_auth_basic_module-禁用ngx_http_auth_basic_module --without-http_autoindex_module-禁用ngx_http_autoindex_module --without-http_geo_module-禁用ngx_http_geo_module --without-http_map_module-禁用ngx_http_map_module --without-http_referer_module-禁用ngx_http_referer_module --without-http_rewrite_module-禁用ngx_http_rewrite_module.如果启用需要PCRE。 --without-http_proxy_module-禁用ngx_http_proxy_module --without-http_fastcgi_module-禁用ngx_http_fastcgi_module --without-http_memcached_module-禁用ngx_http_memcached_module --without-http_limit_zone_module-禁用ngx_http_limit_zone_module --without-http_empty_gif_module-禁用ngx_http_empty_gif_module --without-http_browser_module-禁用ngx_http_browser_module --without-http_upstream_ip_hash_module-禁用ngx_http_upstream_ip_hash_module --with-http_perl_module-启用ngx_http_perl_module --with-perl_modules_pathPATH-指定perl模块的路径 --with-perl=PATH指定perl执行文件的路径 --http-log-path=PATH设置http的访问日志的路径 --http-client-body-temp-path=PATH-Setpathtothehttpclientrequestbodytemporaryfiles --http-proxy-temp-path=PATH-Setpathtothehttpproxytemporaryfiles --http-fastcgi-temp-path=PATH-Setpathtothehttpfastcgitemporaryfiles --without-http禁用HTTPserver --with-mail启用IMAP4/POP3/SMTP代理模块 --with-mail_ssl_module启用ngx_mail_ssl_module --with-cc=PATH指定C编译器的路径 --with-cpp=PATH指定C预处理器的路径 --with-cc-opt=OPTIONS-AdditionalparameterswhichwillbeaddedtothevariableCFLAGS.WiththeuseofthesystemlibraryPCREinFreeBSD,itisnecessarytoindicate--with-cc-opt="-I/usr/local/include".Ifweareusingselect()anditisnecessarytoincreasethenumberoffiledescriptors,thenthisalsocanbeassignedhere:--with-cc-opt="-DFD_SETSIZE=2048". --with-ld-opt=OPTIONS-Additionalparameterspassedtothelinker.WiththeuseofthesystemlibraryPCREinFreeBSD,itisnecessarytoindicate--with-ld-opt="-L/usr/local/lib". --with-cpu-opt=CPU-为特定的CPU编译,有效的值包括:pentium,pentiumpro,pentium3,pentium4,athlon,opteron,amd64,sparc32,sparc64,ppc64 --without-pcre-禁止PCRE库的使用。同时也会禁止HTTPrewrite模块。在"location"配置指令中的正则表达式也需要PCRE。 --with-pcre=DIR-指定PCRE库的源代码的路径。 --with-pcre-opt=OPTIONS-SetadditionaloptionsforPCREbuilding. --with-md5=DIR-Setpathtomd5librarysources. --with-md5-opt=OPTIONS-Setadditionaloptionsformd5building. --with-md5-asm-Usemd5assemblersources. --with-sha1=DIR-Setpathtosha1librarysources. --with-sha1-opt=OPTIONS-Setadditionaloptionsforsha1building. --with-sha1-asm-Usesha1assemblersources. --with-zlib=DIR-Setpathtozliblibrarysources. --with-zlib-opt=OPTIONS-Setadditionaloptionsforzlibbuilding. --with-zlib-asm=CPU-UsezlibassemblersourcesoptimizedforspecifiedCPU,validvaluesare:pentium,pentiumpro --with-openssl=DIR-SetpathtoOpenSSLlibrarysources --with-openssl-opt=OPTIONS-SetadditionaloptionsforOpenSSLbuilding --with-debug-启用调试日志 --add-module=PATH-Addinathird-partymodulefoundindirectoryPATH 3,正式编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [root@centos6   nginx-1.2.9]#./configure --prefix=/usr --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/tmp/nginx/client --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-http_stub_status_module [root@centos6    nginx-1.2.9]#make  &&   make install [root@centos6   nginx-1.2.9]#/usr/sbin/nginx -c  /etc/nginx/nginx.conf nginx:[emerg]mkdir()"/var/tmp/nginx/client"failed(2:Nosuchfileordirectory) [root@centos6  nginx-1.2.9]#mkdir/var/tmp/nginx/client   -p [root@centos6  nginx-1.2.9]#/usr/sbin/nginx -c  /etc/nginx/nginx.conf [root@centos6nginx-1.2.9]#ps-ef| grep   nginx root54791004:15?00:00:00nginx:masterprocess/usr/sbin/nginx-c/etc/nginx/nginx.conf nginx54805479004:15?00:00:00nginx:workerprocess root54832377004:15pts/100:00:00grepnginx




本文转自陈仲阳0 51CTO博客,原文链接:http://blog.51cto.com/wolfword/1204937

相关内容