web service

 

Web Service

Introduction

Nginx: web server(static contents), web reverse proxy(http,mail)

varnish, squid, 做缓存服务器

​ nginx: cache(disk)

​ httpd: cache(memory, disk)

haproxy: tcp reverse proxy, http reverse proxy

ats: apache traffic server

MogileFS, 图片存储分布式文件系统

NoSQL(MongoDB) 文档存储数据库

DMA: 直接内存访问, 找一段连续的内存地址. DMA控制芯片. 讲数据从磁盘上加载至内存中. DMA芯片具有总线的控制权

HTTP Protocal

request ---> response

请求报文:

<method> <URL> <version>
<hearders>
...
<body>

响应报文:

<version> <status code> <reason phrase>
<headers>
...
<body>

响应码:

	1xx: 状态信息码
	2xx: 成功响应码
		200
	3xx: 重定向
		301
		302
		304
	4xx: 客户端错误
	5xx: 服务器端错误

html, css(cascading style sheet)级联样式表,实现丰富的页面元素展示 js,jpg,png,gif

响应效率: 静态 > 动态 > database

note: LNMP中,php与nginx一起使用,必须工作在FPM模式下,fast cgi

stateless: 无状态

​ web page: web object 组成

​ http: 80/tcp

​ tcp 三次握手,四次断开

​ keepalive: 保持连接状态

​ 时间: timeout

​ 数量:

​ cookie: 服务器端返回给客户端唯一的标示 set-cookie. 用户信息的追踪,让用户的访问状态被服务器追踪

​ session保持:session绑定,反均衡,session无高可用

​ session复制:服务器资源消耗过大,网络资源受限

​ session服务器:服务器自身的单点故障,所以要使用高可用

​ lvs session绑定:

​ sh算法: 基于源IP做绑定

​ presistent connection: 持久连接,同样是基于源IP做绑定

​ cookie均衡:Tengine

IO模型:

内核将数据从硬盘调度到内核内存,数据从内核内存到用户空间的进程内存。第二阶段才是真正的I/O调用执行的阶段。第一阶段是磁盘IO

通常所说的同步

​ 同步阻塞 : 数据从磁盘到内核内存,再从内核内存到用户进程内存都是阻塞的状态 ​ 同步非阻塞: 用户进程发起I/O请求,数据从磁盘到内核内存,用户进程处于忙等状态,数据从内核内存到进程内存是阻塞状态 ​ IO复用: select; poll. 内核空间用来检测内核空间的调用是否完成的机制。阻塞在select和poll上。用户空间通过调用select(),poll()函数来返回内核空间的IO调用状态(包括已经完成的和未完成的) ​ 事件通知:无需轮寻。内核通知用户空间数据准备阶段完成。通过call back,回调机制知道是哪个进程发起的调度 ​ 异步:用户空间发起调度以后,所有工作都由内核来完成。只能磁盘I/O做异步,网络I/O无法做到

如果连第二个阶段数据复制也不用做当然最好,内核内存空间直接共享给用户空间的机制,称为内存共享。

如果连数据到内核内存也不需要了,则可以使用MMAP,内存映射机制。直接在磁盘上将数据划分为页面格式,直接把一个文件直接映射到内核内存中,内核再将映射内容内存共享给用户进程

mmap: 数据由磁盘直接以页面形式映射进入到内存中

Prefork使用select(), 最大连接数不能超过1024个

Direct IO: 将缓存和缓冲机制关闭,则可以省去数据从磁盘copy到内核内存的过程。使用进程直接访问磁盘的过程

MPM:

​ prefork: 一个进程响应一个请求, 1024

​ worker: 一个线程响应一个请求, 多进程,一个进程生成多个线程(性能并没有改进,并发连接数并没有改进)

​ event: 基于事件驱动来实现, epoll()

 

并发编程:处理并发用户请求

单进程模型:串行方式响应, 阻塞

多进程模型:prefork, 一个进程响应一个用户请求,金成亮大, 进程间切换次数过多, 并发使用多个进程实现;一个master,多个worker. 每个进程的地址空间是独立的, 很多空间是重复的数据, 所以内存的使用效率较低.

多线程模型:worker, 一个进程生成多个线程,一个线程响应一个用户请求,并发使用多个线程实现.

线程依然需要切换, 轻量级切换.

​ 同一个进程的线程可以共享进程的诸多资源, 比如打开的文件,传入的信号等等

​ 对内存的需求较之进程略有下降.

​ 快速切换时, 会带来线程抖动

多进程多线程模型: 使用多进程生成多线程,n进程,n*m个线程

多线程, N个请求: 一个线程响应多个请求.

事件模型:event, 一个线程直接响应多个用户请求。基于事件驱动机制来维持多个用户请求. epoll())

​ 多路IO, IO复用

 

Nginx

Nginx: engine x

Apache: MPM

​ prefork: 一个进场相应一个请求

​ event(2.4以后):

c10k问题,并发超过10k. 问题

Nginx特性

​ 基本功能:

​ 静态资源的web服务器,自动缓存打开的文件描述符

​ 反向代理服务器,缓存、负载均衡

​ 支持FastCGI协议,能更跟php的FPM服务器结合

​ 模块化机制,非DSO机制,过滤器gzip,SSI和图像大小调整等

​ 支持SSL

​ 扩展功能:

​ 基于名称和IP做虚拟主机

​ 支持keepalive

​ 支持平滑配置更新活程序版本升级

​ 定制访问日志,支持使用日志缓存以提高性能

​ 支持URL rewrite,url地址重写

​ 支持路径别名

​ 文件基于IP及用户的认证

​ 支持速率限制,并发限制等

Tengine, 淘宝发行版. 整合了很多功能

Nginx架构

1、master--worker

​ 一个master,生成一个或多个worker

​ 一般而言worker的个数小于CPU的物理核心数,为了降低CPU的上下文切换

2、事件驱动:kqueue, epoll, /dev/poll

​ 消息通知:select, poll, rt signals

3、支持sendfile,从内核直接产生响应,而无需用户空间的参与。sendfile64,支持的单个文件大小

4、支持AIO,支持纯异步IO

5、支持mmap

nginx: 非阻塞模型、事件驱动、一个master多个worker,一个workder响应多个用户请求

Nginx的模块类别

  • 核心模块
  • 标准http模块
  • 可选http模块
  • 邮件模块
  • 第三方扩展模块

Nginx安装

Nginx的配置文件:

​ main配置段

​ http {}

​ events{}

配置参数需要以分号结尾,语法格式:参数名 value1 [value2 ...];

​ 还支持使用变量:1、模块内置变量 2、用户自定义变量 set var_name value

Nginx基本配置的类别:

​ 用于调试、定位问题

​ 正常运行的必备配置

​ 优化性能的配置

​ 事件类的配置

worker进程应该以普通用户身份运行:nginx用户、nginx组

​ HTTP的方法:GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE

准备工作:

需要安装pcre-devel,重写引擎. Perl-compatible regular expressions

编译安装

添加用户

groupadd -r nginx
useradd -r -g nginx nginx

编译并安装

 
 
 
 
 
AخA
 
 
 
./configure \
  --prefix=/usr \
  --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.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_stub_status_module \
  --with-http_gzip_static_module \
  --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/ \
  --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
  --http-scgi-temp-path=/var/tmp/nginx/scgi \
  --with-debug \
  --with-pcre|tee ~/nginx.out
 
 

--http_flv_module: flash流媒体

--temp-path: 临时缓存目录

--uwsgi: 为Python开发的CGI接口

Configuration Summary

  + using system PCRE library
  + using system OpenSSL library
  + md5: using OpenSSL library
  + sha1: using OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr"
  nginx binary file: "/usr/sbin/nginx"
  nginx modules path: "/usr/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/var/run/nginx/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "/var/tmp/nginx/client/"
  nginx http proxy temporary files: "/var/tmp/nginx/proxy/"
  nginx http fastcgi temporary files: "/var/tmp/nginx/fcgi/"
  nginx http uwsgi temporary files: "/var/tmp/nginx/uwsgi"
  nginx http scgi temporary files: "/var/tmp/nginx/scgi"

note:nginx.vim 可以高亮nginx语法

Install details:

[[ -d ~/.vim/syntax ]] || mkdir  -p ~/.vim/syntax
cd ~/.vim/syntax
wget http://www.vim.org/scripts/download_script.php?src_id=14376 -O nginx.vim
echo "au BufRead,BufNewFile /usr/local/nginx/* set ft=nginx" >> ~/.vim/filetype.vim

Nignx的core配置

http://nginx.org/en/docs/

正常运行的必须配置

​ user username [groupname];

​ 指定运行worker进程的用户和组

​ pid /path/to/pidfile_name;

​ 指定nginx的pid文件

​ worker_rlimit_nofile #;

​ 指定每个worker process可以打开的最大文件句柄数

​ woker_rlimit_sigpending #;

​ 设定每个用户能够发往worker进程的信号的数量

优化性能相关的配置

​ worker_processes #;

​ woker进程的个数:每个worker进程都是单线程,通常其数值应该为CPU的物理核心数减1;

​ worker_cpu_affinity cpumask ...;

​ CPU掩码假设有4颗CPU: 0000 0001(第一颗) 0010 0100 1000

eg.
worker_process 6;
worker_cpu_affinity 00000001 00000010 00000100 00001000 0010000 00100000; 	

​ ssl_engine device;

​ 在存在ssl硬件加速器的服务器上,指定所使用的ssl硬件加速设备;

​ timer_resolution ;

​ 每次内核事件调用返回时,都会使用gettimeofday()系统调用来获得系统调用事件,来更新nginx中的缓存时 钟.早期gettimeofday()的调用成本非常大. timer_resolution 表示不论调用多少次,只在固定的时间间隔才返回系统时间. 目前而言x86-64系统上,gettimeofday()代价已经很小,可以忽略此配置

​ worker_priority ;

​ nice值范围-20,19之间的值

事件相关的配置

​ accept_mutex [on|off];

​ 是否打开nginx的负载均衡锁;此锁能够让多个worker进程轮流地,序列化地与新的客户端建立TCP连接; 通常当一个worker进程的负载达到其上限的7/8, master就尽可能不再将请求调度此worker;

​ lock_file /path/to/lock_file;

​ lock文件

​ accept_mutex_delay #ns;

​ 使用accept锁模式中,一个worker进程为取得accept锁的等待时长;如果某worker进程在某次试图取得锁时失败了,至少要等待 #ms才能再一次请求锁.默认是为500ms

​ multi_accept on|off;

​ 是否允许一次性地响应多个用户请求; 默认为off,即一个连接一个连接建立

​ use [epoll|rtsig|select|poll]

​ 定义使用的时间模型,建议让nginx自动选择;linux上一般选择的是epoll

​ worker_connection #;

​ 每个worker能够并发响应的最大请求数

用于调试,定位问题

只在调试Nginx时使用

​ daemon [on|off];

​ 是否让nginx运行在后台: 默认为on,调试时可以设置为off, 使得所有信息直接输出在控制台;

​ master_process [on|off];

​ 是否以master/worker模式运行nginx,默认为on,调试时可以设置为off,以方便追踪

​ error_log /path/to/error_log ;

​ 错误日志文件及其级别,调试时可以使用debug级别,但要求在编译时必须使用--with-debug启用debug功能

nignx的http功能

必须使用虚拟主机来配置站点;每个虚拟主机使用一个server{}段来配置

​ server {

​ }

非虚拟主机的配置或公共配置, 需要定义在server之外, http之内;

server{}

定义一个虚拟主机: nginx支持使用基于主机名或IP的虚拟机主机;

listen

​ listen address[:port];

​ listen port

​ listen unix:socket_file_path

​ defautl_server; 默认此server为http中默认的server(IP访问),如果所有的server中都没有任何一个listen使用此参数,那么第一个server为默认server

​ rcvbuf=SIZE: 接受缓冲大小

​ sndbuf=SIZE: 发送缓冲大小

​ ssl: https server; 建立连接时必须使用ssl

server_name [...];

​ server_name可以跟多个主机名,名称中可以使用通配符; 当nginx收到一个请求时,会取出其首部的server值,而后跟众server_name进行比较,比较方式为:

  • 先做精确匹配: www.example.com
  • 左侧通配符匹配: *.example.com
  • 右侧通配符匹配: www.*
  • 正则表达式匹配: 匹配前通常需要加破浪符号 ~^.*\.example\.com$

server_name_hash_bucket_size

​ server_name_hash_bucket_size 32|64|128; 为了实现快速主机查找,nginx使用hash来保存主机名

location

​ location [ = | ~ | ~* | ^~ ] uri { ... }

​ location @name { ... }

​ 功能: 允许根据用户请求的URI来匹配指定的各location来进行访问配置, 匹配到时,将被location块中的配置所处理 eg. http://www.example.com/imges/logo.gif

=: 做精确匹配;
~: 正则表达式的模式匹配,匹配时区分字符大小写;
~*: 正则表达式模式匹配,匹配时忽略字符大小写;
^~: URI前半部分匹配,不检查正则表达式

匹配优先级:

​ 字符字面量(字符精确比较)-->正则表达式检索(由第一个匹配到所处理)-->按照字符字面量

文件路径定义:

1 . root path

​ 设置web资源路径,用于指定请求的跟文档目录; root: root/URI

location / {
  	root /www/htdocs;
}
location ^~ /images/ {
   	root /web;
}

2 . alias path

​ 只能用于location中,用于路径别名; alias: alias/

location / {
  	root /www/htdocs;
}
location ^~ /images/ {
   	alias /web;
}
以web来alias images...

3 . index file ....;

​ 定义默认页面, 可以跟多个值, 自左而右逐个匹配

4 . error_page code ... [=[response]] uri;

​ 当对于某个请求返回错误时,如果匹配上了error_page指令中设定的code,则重定向到新的URI中. 简而言之: 错误页面重定向. =response 表示使用新的状态码显示

5 . try_files path1 [path2 ...] uri;

​ 自左至右尝试去读取由path所指定路径,在第一次找到即停止并返回; 如果所有path均不存在, 则返回最后一个uri; $uri 变量表示用户尝试访问的uri

        location ~* ^/documents/(.*)$ {
            root /www/htdocs;
            try_files $uri /docu/$1 /temp.html;
        }
        则会尝试去匹配:
        http://192.168.48.131/documents/a.html
        http://192.168.48.131/docu/a.html
        http://192.168.48.131/temp.html
网络连接相关的设置

1 . keepalive_timeout [time];

​ 默认为75s, 保持连接的超时时长

2 . keepalive_requests n;

​ 在一次长连接上允许承载的最大请求数;

3 . keepalive_disable [msie6 | safari | none]

​ 对指定的浏览器禁止使用长连接

4 . tcp_nodelay on|off

​ 对keepalive连接是否使用TCP_NODELAY选项:

5 . client_header_timeout time;

​ 读取http请求首部的超时时间, 默认为60s

6 . client_body_timeout time;

​ 读取http请求包体的超时时长,默认为60s

7 . send_timeout time;

​ 发送响应的超时时长

对客户端请求的限制

1 . limit_except method ...{...}

​ 指定对范围之外的其他方法的访问控制;

limit_except GET {
  	allow 192.168.48.0/24;
  	deny all;
}

2 . client_max_body_size SIZE;

​ http请求包体的最大值; content-lengh. 常用于限定客户所能够请求的最大包体; 根据请求首部中的content-length来检测, 以避免无用的传输

3 . limit_rate speed;

​ 限制客户端每秒钟能够传输的字节数; 默认为0, 表示没有限制; 默认单位为字节, 也可以指定单位 eg. 40k

4 . limit_rate_after time;

​ nginx向客户端发送响应报文时, 如果时长超过此处指定的时长, 则后续的的发送过程开始限速

文件操作的优化

1 . sendfile on|off

​ 是否启用sendfile功能;

2 . aio on|off

​ 是否启用aio功能;

3 . open_file_cache max=N [inactive=time]|off

​ 是否打开文件缓存功能;

​ max: 用于指定缓存条目的最大值, 当缓存满了之后将根据LRU算法进行置换;

​ inactive: 非活动时间, 缓存条目在指定时长内没有被访问过时, 将自动被删除. 默认为60s

​ 缓存的信息包括:

文件句柄 (文件描述符), 文件大小和上次修改时间

已经打开的目录结构

没有找到活没有访问权限的信息

4 . open_file_cache_errors on|off

​ 是否缓存文件找不到活没有权限访问等相关信息; 可能会影响更新...

5 . open_file_cache_valid time;

​ 多长时间检查一次缓存中的条目是否超出非活动时长地, 默认为60s

6 . open_file_cache_min_use #;

​ 在inactive指定的时长内被访问超此处指定的次数, 才不会被删除. 即命中率太低就被删除

对客户端请求的特殊处理

1 . ignore_invalid_headers on|off

​ 是否忽略不合法的http首部; 默认为on; off意味着请求首部中出现不合规的首部时,拒绝响应; 只能用于server和http;

2 . log_not_found on|off

​ 是否将文件找不到的信息也记录进错误日志中:

3 . resolver address;

​ 指定nginx使用的dns服务器地址;

4 . resolver_timeout time;

​ 指定DNS解析超时时长, 默认为30s; 时间通常需要调短

5 . server_tokens on|off;

​ 是否在错误页面中显示nginx的版本号;

http核心模块的内置变量

$uri: 当前请求的uri, 不带参数;

$host: http请求报文中的host首部; 如果请求中没有host首部, 则以处理此请求的虚拟机主机的主机名代替

$request_uri: 请求的uri, 带完整参数;

$hostname: nginx服务运行所在主机的主机名

$remote_addr: 客户端IP

$remote_port: 客户端端口

$remote_user: 使用用户认证时客户端用户输入的用户名

$request_filename: 用户请求中的URI经过本地root或alias转换后映射的本地的文件路径

$request_method: 请求方法

$server_addr: 服务器地址

$server_name: 服务器名称

$server_port: 服务器端口

$server_protocol: 服务器向客户端发送响应时的协议, http/1.1, http/1.0

$scheme: 在请求中使用的scheme, eg. https://www.example.com中的https

$http_HEADER: 匹配请求报文中指定的HEADER, $http_host匹配请求报文中的host首部

$sent_http_HEADER: 匹配响应报文中指定的HEADER, eg $sent_http_content_type匹配响应报文中的content-type首部;

$document_root: 当前请求映射到的root配置项

配置使用nginx

1 . 虚拟主机

​ nginx必须配置虚拟主机

server {
  	listen
  	server_name
  	root
}

2 . 访问控制access模块

​ allow

​ deny

3 . 用户认证功能

​ auth_basic

​ auth_basic_user_file

location /dmz/ {
  	root /www/b.org;
  	auth_basic "dmz zone";
  	auth_basic_user_file /etc/nginx/.htpasswd;
}
htpasswd -c -m /etc/nginx/.htpasswd esunyig
htpasswd -m /etc/nginx/.htpasswd dora

4 . 建立下载站点autoindex模块

​ autoindex on;

​ 默认为off

5 . 防止盗链

​ 定义合规的引用

​ valid_referers none | blocked | server_names | string ...;

​ 拒绝不合规的引用

if  ($invalid_referer) {
	rewrite ^/.*$ http://www.b.org/403.html 
} 
eg. 
location ~*\.(jpg|png|gif|jpeg)$ {                
    root /www/b.org/images/;                      
    valid_referers none blocked www.b.org *.b.org;
    if ($invalid_referer) {                       
        rewrite ^/ http://www.b.org/403.html;     
    }                                             
}                                       

6 . URL Rewrite

​ rewrite regex replacement [flag];

last: 一旦被当前规则匹配并重写后立即停止检查后续的其他rewrite规则, 而通过重写后的规则重新发起请求

break: 一旦被当前规则匹配并重写后立即停止后续的其他rewrite规则, 而后续由nginx进行后续操作

redirect: 返回302临时重定向

permanent: 返回301永久重定向

location /download/{
  rewrite ^(/download/.*)/media/(.*)\..*$ $1/media/$2.mp3 break;
}

nginx最多循环10次, 超出之后返回500错误.

注意: 一般将rewrite卸载location中时都是用break标记, 或者将rewrite写在if上下文中;

rewrite_log on|off

​ 是否把重写过程记录在错误日志中, 默认为notice级别, 默认为off

return code:

​ 用于结束rewrite规则, 并且为客户端返回状态码, 可以使用的状态码有204, 400, 402-406, 500-504等

gzip

http {
	gzip on;
	gzip_http_version 1.0;
	gzip_comp_level 2;
	gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/json;
	gzip_disable msie6;
}

gzip_proxied指令可以定义对客户端请求哪类对象启用压缩功能,如“expired”表示对由于使用了expire首部定义而无法缓存的对象启用压缩功能,其它可接受的值还有“no-cache”、“no-store”、“private”、“no_last_modified”、“no_etag”和“auth”等,而“off”则表示关闭压缩功能。

note: 实际对图片压缩没有意义, 本身压缩比比较小

反向代理功能

xcache用于缓存app server的编译结果,并在app server之间实现共享

fastcgi

location ~*\.php$ {
  	fastcgi_pass 127.0.0.1:9000;
}

fastcgi模块的常用指令:

fastcgi_pass: 指定fastcgi服务监听端口、地址;也支持使用Unix sock;
fastcgi_bind: 指定联系fpm服务时使用的地址;
fastcgi_param: 定义传递给fpm服务器的参数;
fastcgi_index: php的主页面文件;

结果可以缓存, 缓存空间使用fastcgi_path定义, 使用fastcgi_cache来调用:

fastcgi_cache_path
fastcgi_cache
fastcgi_cache_valid
fastcgi_connect_timeout: 连接fastcgi服务器的超时时长;
fastcgi_send_timeout: 向fastcgi服务传输数据的超时时长 ;

获取php-fpm的状态信息:

 location ~* /(status|ping) {
 	root           /www/a.com;
	fastcgi_pass   127.0.0.1:9000;
	fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
	include        fastcgi_params;
  }

fastcgi_params配置文件

fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFWARE    nginx;
fastcgi_param QUERY_STRING      $query_string;
fastcgi_param REQUEST_METHOD    $request_method;
fastcgi_param CONTENT_YTPE      $content_type;
fastcgi_param CONTENT_LENGTH    $content_length;
fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME       $fastcgi_script_name;
fastcgi_param REQUEST_URI       $request_uri;
fastcgi_param DOCUMENT_URI      $document_uri;
fastcgi_param DOCUMENT_ROOT     $document_root;
fastcgi_param SERVER_PROTOCOL   $server_protocol;
fastcgi_param REMOTE_ADDR       $remote_addr;
fastcgi_param REMOTE_PORT       $remote_port;
fastcgi_param SERVER_ADDR       $server_addr;
fastcgi_param SERVER_PORT       $server_port;
fastcgi_param SERVER_NAME       $server_name;

php-fpm状态参数

pool	www
	进程池的名称;
process manager	dynamic
	进程管理器,有两种类型static和dynamic;
start time	25/Apr/2014:15:28:07 +0800
	起动时间
start since	2150
	运行时长
accepted conn	4021
	已经接受的请求数;
listen queue	0
	等待队列中的请求的个数;
max listen queue	90
	fpm启动以来等待队列中的请求的总数;
listen queue len	128
	等待队列长度
idle processes	4
	空闲的进程数
active processes	1
	活动进程数
total processes	5
	总进程数
max active processes	8
	ftp启动以来最大活动进程数
max children reached	0
	达到最大子进程的次数
slow requests	0
	慢速请求的个数

反向代理

proxy_pass

location [op] URI {
  
}
操作符
~	区分大小写,元字符匹配
~*	不区分大小写,元字符匹配
^~ 	逐个字符匹配
= 	路径精确匹配,通常匹配文件
location /forum/ {
  	proxy_pass http://192.168.48.132/bbs/:80
}
模式匹配的情况下, proxy server的路径不可以指定 eg.
location ~* ^/forum {
  	proxy_pass http://192.168.48.132:8080;
}

如果在location中使用URL重定向, 那么nginx将使用重定向后的URI处理请求, 而不再考虑上游服务器上定义的URI

proxy_set_header

在nginx配置中添加首部

proxy_set_header X-Real-IP $remote_addr

在httpd的log格式中修改

LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" co
mbined
其中%{X-Real-IP}代表变量值

http method:

GET, POST, HEAD, PUT, TRACE, OPTIONS, CONNECTION, DELETE

nginx支持的算法

​ round-robin

​ ip_hash

​ least_conn

配置eg.

upstream websrvs {
    #ip_hash
    server 192.168.48.132 weight=1 max_fails=2 fail_timeout=2;
    server 192.168.48.137 weight=1 max_fails=2 fail_timeout=2;
    server 127.0.0.1:8080 backup;
}
location / {
    proxy_pass http://websrvs/;
    proxy_set_header X-Real-IP $remote_addr;
}
server {
    listen 8080;
    server_name localhost;
    root /web/errorpages;
    index index.html;
}

cache:

共享内存, 存储键和缓存对象元数据

​ 磁盘空间:存储数据

proxy_cache_path: 不能定义在server{}上下文中;

定义三级缓存目录,以first为缓存空间名称

proxy_cache_path /nginx/cache/first levels=1:2:1 keys_zone=first:20m max_size=1G;

cache_manager: LRU 最近最少使用算法

WebDAV(Web-based Distributed Authoring and Versioning) 一种基于HTTP 1.1协议的通信协议, 它扩展了HTTP1.1, 在GET, POST, HEAD等几个HTTP标准方法以外添加了一些新的方法, 使得应用程序可直接对Web Server直接读写, 并支持写文件锁定(Locking)及解锁(Unlock), 还可以支持文件的版本控制

另外常用的三种缓存:

​ open_log_cache

​ open_file_cache

​ fastcgi_cache

Memcache

Glibc 中使用malloc()创建内存空间, free()释放内存

TCmalloc(), 优化内存分配机制

memcache使用 slab allocator来完成内存的分配和回收, 提前对内存分页, 并想内核申请固定大小的内存空间

grow factor: 增长因子, 可以自定义.

Page: 内存页面, 分配给slab用于切割的内存空间, 默认页面大小为1MB, 内核分配给slab之后, slab再根据应用需求进行分配

Chunk: 用户缓存记录的内存空间

slab class: 特定大小的chunk组

memcache协议: 文本格式, 二进制格式

Memcache的特点

  1. 简单key/value存储:服务器不关心数据本身的意义及结构,只要是可序列化数据即可。存储项由“键、过期时间、可选的标志及数据”四个部分组成;
  2. 功能的实现一半依赖于客户端,一半基于服务器端:客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期;
  3. 各服务器间彼此无视:不在服务器间进行数据同步;
  4. O(1)的执行效率
  5. 清理超期数据:默认情况下,Memcached是一个LRU缓存,同时,它按事先预订的时长清理超期数据;但事实上,memcached不会删除任何已缓存数据,只是在其过期之后不再为客户所见;而且,memcached也不会真正按期限清理缓存,而仅是当get命令到达时检查其时长;

一致性哈希算法

libevent库:用于调用并发, epoll(), poll(), select()

每个请求一个线程响应

安装memcached

memcached依赖于libevent API,因此要事先安装之

tar xf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21
./configure --prefix=/usr/local/libevent
make && make install

echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
ldconfig 

安装配置memcached

tar xf memcached-1.4.15.tar.gz 
cd memcached-1.4.15
./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
make && make install

memcached SysV startup脚本

#! /bin/sh
#
# chkconfig: - 55 45
# description:	The memcached daemon is a network memory cache service.
# processname: memcached
# config: /etc/sysconfig/memcached
# pidfile: /var/run/memcached/memcached.pid

# Standard LSB functions
#. /lib/lsb/init-functions

# Source function library.
. /etc/init.d/functions

PORT=11211
USER=memcached
MAXCONN=1024
CACHESIZE=64
OPTIONS=""

if [ -f /etc/sysconfig/memcached ];then 
	. /etc/sysconfig/memcached
fi

# Check that networking is up.
. /etc/sysconfig/network

if [ "$NETWORKING" = "no" ]
then
	exit 0
fi

RETVAL=0
prog="memcached"
pidfile=${PIDFILE-/var/run/memcached/memcached.pid}
lockfile=${LOCKFILE-/var/lock/subsys/memcached}

start () {
	echo -n $"Starting $prog: "
	# Ensure that /var/run/memcached has proper permissions
	if [ "`stat -c %U /var/run/memcached`" != "$USER" ]; then
		chown $USER /var/run/memcached
	fi

	daemon --pidfile ${pidfile} memcached -d -p $PORT -u $USER  -m $CACHESIZE -c $MAXCONN -P ${pidfile} $OPTIONS
	RETVAL=$?
	echo
	[ $RETVAL -eq 0 ] && touch ${lockfile}
}
stop () {
	echo -n $"Stopping $prog: "
	killproc -p ${pidfile} /usr/bin/memcached
	RETVAL=$?
	echo
	if [ $RETVAL -eq 0 ] ; then
		rm -f ${lockfile} ${pidfile}
	fi
}

restart () {
        stop
        start
}

# See how we were called.
case "$1" in
  start)
	start
	;;
  stop)
	stop
	;;
  status)
	status -p ${pidfile} memcached
	RETVAL=$?
	;;
  restart|reload|force-reload)
	restart
	;;
  condrestart|try-restart)
	[ -f ${lockfile} ] && restart || :
	;;
  *)
	echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart|try-restart}"
	RETVAL=2
        ;;
esac

exit $RETVAL

memached的常用选项

-l <ip_addr>:指定进程监听的地址;
-d: 以服务模式运行;
-u <username>:以指定的用户身份运行memcached进程;
-m <num>:用于缓存数据的最大内存空间,单位为MB,默认为64MB;
-c <num>:最大支持的并发连接数,默认为1024;
-p <num>: 指定监听的TCP端口,默认为11211;
-U <num>:指定监听的UDP端口,默认为11211,0表示关闭UDP端口;
-t <threads>:用于处理入站请求的最大线程数,仅在memcached编译时开启了支持线程才有效;
-f <num>:设定Slab Allocator定义预先分配内存空间大小固定的块时使用的增长因子;
-M:当内存空间不够使用时返回错误信息,而不是按LRU算法利用空间;
-n: 指定最小的slab chunk大小;单位是字节;
-S: 启用sasl进行用户认证;
-P: 指定pid文件

启动服务后使用telnet登录memcached

telnet 127.0.0.1 11211

Memcached提供了为数不多的几个命令来完成与服务器端的交互,这些命令基于memcached的协议实现。

存储类命令:set, add, replace, append, prepend
获取数据类命令:get, delete, incr/decr
统计类命令:stats, stats items, stats slabs, stats sizes
清理命令: flush_all
add命令:
add keyname flag  timeout  datasize
如:
add mykey 0 10 12
Hello world!

get命令:
get keyname
如:get mykey
VALUE mykey 0 12
Hello world!
END

程序员在开发时, 自行调用memcached的API, memcached的功能才能生效

​ Memcached: 服务器

​ memcached: php连接memcached服务可以使用扩展

​ memcache: php连接memcached服务可以使用的另一个扩展

​ libmemcached: C库

安装memcache PHP扩展

tar xf memcache-2.2.5.tgz
cd memcache-2.2.5
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache
make && make install

Nginx整个memcached

server {
        listen       80;
        server_name  www.b.org;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
                set $memcached_key $uri;
                memcached_pass     192.168.48.138:11211;
                default_type       text/html;
                error_page         404 @fallback;
        }

        location @fallback {
                proxy_pass http://192.168.48.131;
        }
}

note: memory cache 如果挂掉了, 应该注意灰度发布, 即放一部分流量先行进行缓存

Haproxy

LB:

4 layer: lvs

7 layer:

​ nginx(web, http reverse proxy, cache)

​ haproxy (http reverse proxy, tcp-based proxy)

​ ats (apache traffic server)

​ perlball

​ pound

​ squid

​ varnish

1310法则; 期待站点的等待时长为1s, 3s可以接受

早期HAproxy使用红黑二叉树研发, 后来发现如果频繁的查询, 红黑树在平衡树结构的时候会消耗大量的资源. 后来改进了其算法, 使用弹性二叉树数据结构

版本

HAProxy目前主要有两个版本:

1.4——提供较好的弹性:衍生于1.2版本,并提供了额外的新特性,其中大多数是期待已久的。 客户端侧的长连接(client-side keep-alive) TCP加速(TCP speedups) 响应池(response buffering) RDP协议 基于源的粘性(source-based stickiness) 更好的统计数据接口(a much better stats interfaces) 更详细的健康状态检测机制(more verbose health checks) 基于流量的健康评估机制(traffic-based health) 支持HTTP认证 服务器管理命令行接口(server management from the CLI) 基于ACL的持久性(ACL-based persistence) 日志分析器

1.3——内容交换和超强负载:衍生于1.2版本,并提供了额外的新特性。 内容交换(content switching):基于任何请求标准挑选服务器池; ACL:编写内容交换规则; 负载均衡算法(load-balancing algorithms):更多的算法支持; 内容探测(content inspection):阻止非授权协议; 透明代理(transparent proxy):在Linux系统上允许使用客户端IP直接连入服务器; 内核TCP拼接(kernel TCP splicing):无copy方式在客户端和服务端之间转发数据以实现数G级别的数据速率; 分层设计(layered design):分别实现套接字、TCP、HTTP处理以提供更好的健壮性、更快的处理机制及便捷的演进能力; 快速、公平调度器(fast and fair scheduler):为某些任务指定优先级可实现理好的QoS; 会话速率限制(session rate limiting):适用于托管环境;

配置

http://cbonte.github.io/haproxy-dconv/

配置由两部分组成:

global settings: 对haproxy进程自身属性的设定

proxies: 对代理的设定

​ defaults

​ frontend

​ backend

​ listen

HAProxy的配置处理3类来主要参数来源: ——最优先处理的命令行参数, ——“global”配置段,用于设定全局配置参数; ——proxy相关配置段,如“defaults”、“listen”、“frontend”和“backend”;

时间格式

一些包含了值的参数表示时间,如超时时长。这些值一般以毫秒为单位,但也可以使用其它的时间单位后缀。 us: 微秒(microseconds),即1/1000000秒; ms: 毫秒(milliseconds),即1/1000秒; s: 秒(seconds); m: 分钟(minutes); h:小时(hours); d: 天(days);

全局配置

“global”配置中的参数为进程级别的参数,且通常与其运行的OS相关。

  • 进程管理及安全相关的参数

    • chroot :修改haproxy的工作目录至指定的目录并在放弃权限之前执行chroot()操作,可以提升haproxy的安全级别,不过需要注意的是要确保指定的目录为空目录且任何用户均不能有写权限;
    • daemon:让haproxy以守护进程的方式工作于后台,其等同于“-D”选项的功能,当然,也可以在命令行中以“-db”选项将其禁用;
    • gid :以指定的GID运行haproxy,建议使用专用于运行haproxy的GID,以免因权限问题带来风险;
    • group :同gid,不过指定的组名;
    • log
      [max level [min level]]:定义全局的syslog服务器,最多可以定义两个;
    • log-send-hostname []:在syslog信息的首部添加当前主机名,可以为“string”指定的名称,也可以缺省使用当前主机名;
    • nbproc :指定启动的haproxy进程的个数,只能用于守护进程模式的haproxy;默认只启动一个进程,鉴于调试困难等多方面的原因,一般只在单进程仅能打开少数文件描述符的场景中才使用多进程模式;
    • pidfile:
    • uid:以指定的UID身份运行haproxy进程;
    • ulimit-n:设定每进程所能够打开的最大文件描述符数目,默认情况下其会自动进行计算,因此不推荐修改此选项;
    • user:同uid,但使用的是用户名;
    • stats:
    • node:定义当前节点的名称,用于HA场景中多haproxy进程共享同一个IP地址时;
    • description:当前实例的描述信息;
  • 性能调整相关的参数

  • maxconn :设定每个haproxy进程所接受的最大并发连接数,其等同于命令行选项“-n”;“ulimit -n”自动计算的结果正是参照此参数设定的;
  • maxpipes :haproxy使用pipe完成基于内核的tcp报文重组,此选项则用于设定每进程所允许使用的最大pipe个数;每个pipe会打开两个文件描述符,因此,“ulimit -n”自动计算时会根据需要调大此值;默认为maxconn/4,其通常会显得过大;

设定一个前端的最大并发连接数,因此,其不能用于backend区段。对于大型站点来说,可以尽可能提高此值以便让haproxy管理连接队列,从而避免无法应答用户请求。当然,此最大值不能超出“global”段中的定义。此外,需要留心的是,haproxy会为每个连接维持两个缓冲,每个缓冲的大小为8KB,再加上其它的数据,每个连接将大约占用17KB的RAM空间。这意味着经过适当优化后,有着1GB的可用RAM空间时将能维护40000-50000并发连接。

如果为指定了一个过大值,极端场景下,其最终占据的空间可能会超出当前主机的可用内存,这可能会带来意想不到的结果;因此,将其设定了一个可接受值方为明智决定。其默认为2000。

  • noepoll:在Linux系统上禁用epoll机制;
  • nokqueue:在BSE系统上禁用kqueue机制;
  • nopoll:禁用poll机制;
  • nosepoll:在Linux禁用启发式epoll机制;
  • nosplice:禁止在Linux套接字上使用内核tcp重组,这会导致更多的recv/send系统调用;不过,在Linux 2.6.25-28系列的内核上,tcp重组功能有bug存在;
  • spread-checks <0..50, in percent>:在haproxy后端有着众多服务器的场景中,在精确的时间间隔后统一对众服务器进行健康状况检查可能会带来意外问题;此选项用于将其检查的时间间隔长度上增加或减小一定的随机时长;
  • tune.bufsize :设定buffer的大小,同样的内存条件小,较小的值可以让haproxy有能力接受更多的并发连接,较大的值可以让某些应用程序使用较大的cookie信息;默认为16384,其可以在编译时修改,不过强烈建议使用默认值;
  • tune.chksize :设定检查缓冲区的大小,单位为字节;更大的值有助于在较大的页面中完成基于字符串或模式的文本查找,但也会占用更多的系统资源;不建议修改;
  • tune.maxaccept :设定haproxy进程内核调度运行时一次性可以接受的连接的个数,较大的值可以带来较大的吞吐率,默认在单进程模式下为100,多进程模式下为8,设定为-1可以禁止此限制;一般不建议修改;
  • tune.maxpollevents :设定一次系统调用可以处理的事件最大数,默认值取决于OS;其值小于200时可节约带宽,但会略微增大网络延迟,而大于200时会降低延迟,但会稍稍增加网络带宽的占用量;
  • tune.maxrewrite :设定为首部重写或追加而预留的缓冲空间,建议使用1024左右的大小;在需要使用更大的空间时,haproxy会自动增加其值;
  • tune.rcvbuf.client :
  • tune.rcvbuf.server :设定内核套接字中服务端或客户端接收缓冲的大小,单位为字节;强烈推荐使用默认值;
  • tune.sndbuf.client:
  • tune.sndbuf.server:
  • Debug相关的参数

    • debug
    • quiet
Keyword

bind [

]:<port_range> [,....]
listen http_proxy
bind :80, :443
bind 10.0.0.1:10080, 10.0.0.1:10443 
Balance及算法

balance []

调度算法

roundrobin; static-rr; leastconn; source ; uri ; uri_param ; hdr(); rdp-cookie;

roundrobin支持动态加入server,但是有有4096个后端服务器的限制

leastconn是一种wlc的连接

source: 基于源IP的hash, 第一次连接时使用wlc的机制, 此后根据source ip做会话保持. 一般只有不支持使用cookie插入又要保持会话时使用

uri: 用于后端服务器是cache server的场景, 能够提高缓存命中率. hash-type可以指定一致性hash算法, 并且可以支持使用截取uri, 使用len指定截取URI长度以及depth指定截取URI的深度(/分隔深度)

url-params: 差用于后端服务器需要对用户进行认证的场景中, 也可以指定hash-type指定一致性hash算法. 当url中缺乏pararms, 则根据roundrobin进行分布

hdr: 根据http的请求首部进行hash计算. 如果针对首部, 可以指定附加选项 use_domain_only的选项, 来仅仅指定域名.(泛域名的场景). 实现将对同一个虚拟主机的访问始终定向至同一个upstream server

rdp-cookie: 针对remote desktop protocol的cookie来做hash计算

算法详解

roundrobin:基于权重进行轮叫,在服务器的处理时间保持均匀分布时,这是最平衡、最公平的算法。此算法是动态的,这表示其权重可以在运行时进行调整,不过,在设计上,每个后端服务器仅能最多接受4128个连接; static-rr:基于权重进行轮叫,与roundrobin类似,但是为静态方法,在运行时调整其服务器权重不会生效;不过,其在后端服务器连接数上没有限制; leastconn:新的连接请求被派发至具有最少连接数目的后端服务器;在有着较长时间会话的场景中推荐使用此算法,如LDAP、SQL等,其并不太适用于较短会话的应用层协议,如HTTP;此算法是动态的,可以在运行时调整其权重; source:将请求的源地址进行hash运算,并由后端服务器的权重总数相除后派发至某匹配的服务器;这可以使得同一个客户端IP的请求始终被派发至某特定的服务器;不过,当服务器权重总数发生变化时,如某服务器宕机或添加了新的服务器,许多客户端的请求可能会被派发至与此前请求不同的服务器;常用于负载均衡无cookie功能的基于TCP的协议;其默认为静态,不过也可以使用hash-type修改此特性; uri:对URI的左半部分(“问题”标记之前的部分)或整个URI进行hash运算,并由服务器的总权重相除后派发至某匹配的服务器;这可以使得对同一个URI的请求总是被派发至某特定的服务器,除非服务器的权重总数发生了变化;此算法常用于代理缓存或反病毒代理以提高缓存的命中率;需要注意的是,此算法仅应用于HTTP后端服务器场景;其默认为静态算法,不过也可以使用hash-type修改此特性; url_param:通过为URL指定的参数在每个HTTP GET请求中将会被检索;如果找到了指定的参数且其通过等于号“=”被赋予了一个值,那么此值将被执行hash运算并被服务器的总权重相除后派发至某匹配的服务器;此算法可以通过追踪请求中的用户标识进而确保同一个用户ID的请求将被送往同一个特定的服务器,除非服务器的总权重发生了变化;如果某请求中没有出现指定的参数或其没有有效值,则使用轮叫算法对相应请求进行调度;此算法默认为静态的,不过其也可以使用hash-type修改此特性; hdr():对于每个HTTP请求,通过指定的HTTP首部将会被检索;如果相应的首部没有出现或其没有有效值,则使用轮叫算法对相应请求进行调度;其有一个可选选项“use_domain_only”,可在指定检索类似Host类的首部时仅计算域名部分(比如通过www.magedu.com来说,仅计算magedu字符串的hash值)以降低hash算法的运算量;此算法默认为静态的,不过其也可以使用hash-type修改此特性; rdp-cookie rdp-cookie(name):

Cookie

cookie node insert nocache

hash-type

map-based

consistent

HAProxy工作模式

http

​ http协议模式, 对应用层数据做深度分析, 支持七层过滤,处理,转换等机制.

tcp

​ 默认模式:

​ haproxy在客户端和upstream server之间建立一个全双工的连接,不会对应用层协议做任何检查. SSL, MySQL, SSL等都应该使用此模式

mode

mode tcp|http|health

日志

log global: 使用全局配置中定义的日志服务器

log

[ []]

capture request header len

capture response header len

指定默认backend

在listen或frontend中指定使用的默认后端:

​ default_backend <backend_name>

在listen或frontend中指定使用的条件式后端:

use_backend if

use_backend unless

定义Server

为backend或listen定义各服务器:

server

[:port][param*]

server first 10.1.1.1:1080 cookie first check inter 1000

server second 10.1.1.1:1080 cookie second check inter 1000

服务器或默认服务器参数: backup:设定为备用服务器,仅在负载均衡场景中的其它server均不可用于启用此server; check:启动对此server执行健康状态检查,其可以借助于额外的其它参数完成更精细的设定,如: inter :设定健康状态检查的时间间隔,单位为毫秒,默认为2000;也可以使用fastinter和downinter来根据服务器端状态优化此时间延迟;` ​ rise

:设定健康状态检查中,某离线的server从离线状态转换至正常状态需要成功检查的次数; fall :确认server从正常状态转换为不可用状态需要检查的次数; cookie :为指定server设定cookie值,此处指定的值将在请求入站时被检查,第一次为此值挑选的server将在后续的请求中被选中,其目的在于实现持久连接的功能; maxconn :指定此服务器接受的最大并发连接数;如果发往此服务器的连接数目高于此处指定的值,其将被放置于请求队列,以等待其它连接被释放; maxqueue :设定请求队列的最大长度; observe :通过观察服务器的通信状况来判定其健康状态,默认为禁用,其支持的类型有“layer4”和“layer7”,“layer7”仅能用于http代理场景; redir :启用重定向功能,将发往此服务器的GET和HEAD请求均以302状态码响应;需要注意的是,在prefix后面不能使用/,且不能使用相对地址,以免造成循环;例如: server srv1 172.16.100.6:80 redir http://imageserver.example.com check weight :权重,默认为1,最大值为256,0表示不参与负载均衡;

使用backup server

server backup 127.0.0.1:8010 check backup

check检查方法

option httpchk 指定检测的方法, 用于指定对http协议的server的检测方法

option httpchk /test1.html` 
Stats

stats enable

stats uri /hpadmin?stats

stats auth admin:admin

访问url uri/haproxy?stats

stats enable
stats uri
stats realm
stats auth
stats admin

使用单独输出eg

listen statistics
    bind *:8009
    stats enable
    stats auth admin:admin
    stats uri /hpadmin?stats
    stats hide-version
    stats admin if TRUE				#认证通过则允许管理
错误页面

errorfile

errorfile <code> <file>

errorloc

在用户请求不存在的页面时,返回一个页面文件给客户端而非由haproxy生成的错误代码;可用于所有段中。

:指定对HTTP的哪些状态码返回指定的页面;这里可用的状态码有200、400、403、408、500、502、503和504; :指定用于响应的页面文件;

例如: errorfile 400 /etc/haproxy/errorpages/400badreq.http errorfile 403 /etc/haproxy/errorpages/403forbid.http errorfile 503 /etc/haproxy/errorpages/503sorry.http

errorloc errorloc302

请求错误时,返回一个HTTP重定向至某URL的信息;可用于所有配置段中。

指定对HTTP的哪些状态码返回指定的页面;这里可用的状态码有200、400、403、408、500、502、503和504; Location首部中指定的页面位置的具体路径,可以是在当前服务器上的页面的相对路径,也可以使用绝对路径;需要注意的是,如果URI自身错误时产生某特定状态码信息的话,有可能会导致循环定向;

需要留意的是,这两个关键字都会返回302状态吗,这将使得客户端使用同样的HTTP方法获取指定的URL,对于非GET法的场景(如POST)来说会产生问题,因为返回客户的URL是不允许使用GET以外的其它方法的。如果的确有这种问题,可以使用errorloc303来返回303状态码给客户端。

errorloc303

请求错误时,返回一个HTTP重定向至某URL的信息给客户端;可用于所有配置段中。

指定对HTTP的哪些状态码返回指定的页面;这里可用的状态码有400、403、408、500、502、503和504; Location首部中指定的页面位置的具体路径,可以是在当前服务器上的页面的相对路径,也可以使用绝对路径;需要注意的是,如果URI自身错误时产生某特定状态码信息的话,有可能会导致循环定向;

http-request

http-request {allow|deny|auth[realm ]} [{if|unless} ]

配置向upstream server发送消息时,保留原client IP

在HAproxy配置中

option forwardfor except 127.0.0.0/8

option forwardfor [ except ][ header ] [ if-none ]

允许在发往服务器的请求首部中插入“X-Forwarded-For”首部。

可选参数,当指定时,源地址为匹配至此网络中的请求都禁用此功能。 可选参数,可使用一个自定义的首部,如“X-Client”来替代“X-Forwarded-For”。有些独特的web服务器的确需要用于一个独特的首部。 if-none:仅在此首部不存在时才将其添加至请求报文问道中。

HAProxy工作于反向代理模式,其发往服务器的请求中的客户端IP均为HAProxy主机的地址而非真正客户端的地址,这会使得服务器端的日志信息记录不了真正的请求来源,“X-Forwarded-For”首部则可用于解决此问题。HAProxy可以向每个发往服务器的请求上添加此首部,并以客户端IP为其value。

需要注意的是,HAProxy工作于隧道模式,其仅检查每一个连接的第一个请求,因此,仅第一个请求报文被附加此首部。如果想为每一个请求都附加此首部,请确保同时使用了“option httpclose”、“option forceclose”和“option http-server-close”几个option。

在HTTP配置中添加环境变量%{X-Format-For}i

LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

option httpclose: 检测首部中是否有connection: close, 如果没有则添加之

option redispatch: 如果后端server的cookie down则打破cookie粘性, 从新派发.

option httplog [ clf ]

启用记录HTTP请求、会话状态和计时器的功能。

clf:使用CLF格式来代替HAProxy默认的HTTP格式,通常在使用仅支持CLF格式的特定日志分析器时才需要使用此格式。

默认情况下,日志输入格式非常简陋,因为其仅包括源地址、目标地址和实例名称,而“option httplog”参数将会使得日志格式变得丰富许多,其通常包括但不限于HTTP请求、连接计时器、会话状态、连接数、捕获的首部及cookie、“frontend”、“backend”及服务器名称,当然也包括源地址和端口号等。

option logasap no option logasap

启用或禁用提前将HTTP请求记入日志,不能用于“backend”区段。

默认情况下,HTTP请求是在请求结束时进行记录以便能将其整体传输时长和字节数记入日志,由此,传较大的对象时,其记入日志的时长可能会略有延迟。“option logasap”参数能够在服务器发送complete首部时即时记录日志,只不过,此时将不记录整体传输时长和字节数。此情形下,捕获“Content-Length”响应首部来记录传输的字节数是一个较好选择。下面是一个例子。

listen http_proxy 0.0.0.0:80

  mode http
  option httplog
  option logasap
  log 172.16.100.9 local2
redirect

redirect location [code ]{if |unless} ]

acl clear dst_port 80
acl secure dst_port 8080
acl login_page url_beg /login 
acl logout url_beg /logout
acl uid_given url_reg /login?userid=[^&]+
acl cooke_set hdr_sub(cookie) SEEN=1
redirect prefix https://centos.example.com set-cookie SEEN=1 if !cookie_set
redirect prefix https://centos.example.com if login_page !secure
redirect prefix http://centos.example.com drop-query if login_page !uid_given
redirect location http://centos.example.com/ if !login_page secure
redirect location / clear-cookie USERID= if logout
reqadd

添加首部报文

reqadd [{if|unless}]

acl is-ssl dst_port 443
reqadd X-Proto:\ SSL if is-ssl

同理rspadd: 添加回复http首部

timeout

timeout http-request 指定超时时长

默认时间为毫秒

timeout queue 队列等待超时时间

timeout connect haporxy 跟上游服务器建立连接的超时时长

timeout client 客户端非响应超时时长

timeout server 等待服务器端发数据的超时时长

timeout http-keep-alive 保持连接的超时时长

ACL

acl flags operator

dst: 目标地址

src: 源地址

dst_port: 目标端口

src_port: 源端口

拒绝src 172.16.100.0/24网段的请求

acl badguy src 172.16.100.0/24

tcp-request content reject if badguy

实现访问控制:

​ http-request: 7层过滤

​ tcp-request content accept/reject: tcp层过滤

hdr(Header)

hdr(Connection) -i close

hdr_reg(Host)

​ path

​ path_beg

​ path_end

​ path_reg

​ url

​ url_beg

eg.

acl url_static path_beg /static /images /img /css
acl url_static path_end .gif .png .jpg .css .js
acl host_www hdr_beg(host) -i www
acl host_static hdr_beg(host) -i img. video. download. 
use_backend static if host_static or host_www or url_static 
use_backend www if host_www

 

 

会话保持机制

IP层: source

​ 位于某一个NAT服务器背后的多个请求都会定向至一个upstream server, 不利于均衡

应用层: cookie

​ 有更好的负载均衡效果

source: 一般只有不支持cookie插入又需要保持会话时使用

Vanish

HTTP首部缓存控制

缓存遵循二八法则. 最近最少算法

7200机械硬盘, iops只能达到80-100

固态硬盘满写最多可以使用十万次. 400-500个ipos

图片本身就是经过高密度压缩, 对其进行压缩不但浪费时间还会浪费CPU时钟周期.

缓存命中率:

​ 文档命中率

​ 字节命中率

缓存类型:

​ 私有缓存

​ 公共缓存

内容路由:

​ 基于缓存协议彼此通信 ICP: Internet Cache Protocol

​ 蓝汛: CDN

​ HTCP: HyperText Caching Protocol

​ Cache Digest

​ Cache Pre-filling

​ CARP: Cache Array Routing Protocol

缓存处理的具体步骤:

​ 接受请求

​ 解析请求(代理)

​ 查询缓存(检查本地缓存中是否存在对方请求的内容的副本)

​ 副本的新鲜度检测(检查本地缓存的副本是否为最新版本)

​ 构建响应(代理的功能)

​ 发送

​ 日志记录

保证副本的新鲜度?

​ 文档过期机制:

​ HTTP/1.0: Expires(过期时间) 绝对时间

​ HTTP/1.1: Cache-Control(max-age=) 相对时长

​ 条件式请求:

​ 304, Not Modified

​ mtime: If-Modified-Since

​ 基于时间的条件式请求

​ ETag: 扩展标记 If-None-Match

​ 基于扩展标签的条件式请求

原始服务器或缓存服务器控制缓存的能力:

​ 由原始服务器定义:

​ Cache-Control

​ max-age: 私有缓存

​ s-maxage: 共有缓存

​ no-store: 不能缓存

​ no-cache: 能缓存, 但是不能直接使用此缓存对象; 缓存对象在使用之前必须做新鲜度认证

​ must-revalidate: 必须进行新鲜度验证

​ priviate: 私有数据

​ public: 公开数据

​ Expires:

​ 原始服务器不添加任何控制机制, 而由缓存服务器自己决定缓存时长

客户端控制是否使用缓存:

​ Cache-Control

​ max-stale: 告知缓存机制可以使用过期的文件

​ no-cache: 告知缓存机制必须进行验证, 否则不会接受任何缓存资源

​ no-store: 告知缓存机制必须尽快删除缓存中的文档

​ HTTP/1.0

​ Pragma: no-cache

http协议

​ request:

​ method url version

​ HEADERS

​ BODY

​ response:

​ version status reason

​ HEADERS

​ BODY

HTTP首部

​ 通用

​ Connection: close|keep-alive 短连接和长连接 HTTP

​ Date: 日期时间, 请求产生的日期时间

​ Host: 请求的主机

​ Pragma: no-cache 缓存服务器必须到原始服务器进行新鲜度验证

​ Via: 请求或响应消息在客户端和服务器之间传递时所经过的代理

​ Transfer-Encoding: 消息主体的传输编码方式, chunked表示采用块编码的方式

​ 请求

​ If-Modified-Since: 基于时间的条件式请求

​ If-None-Mactchd: 基于扩展标签的条件式请求

​ Referer: 通过点击页面中的链接进行跳转

​ User-Agent: 用户的浏览器类型

​ Host: 请求的主机及端口号

​ Accept-Encoding: 接受的编码方式

​ Accept-Language: 接受的自然语言

​ Accept-Charset: 接受字符集

​ Authorization: 服务端发送www-authenticate首部时, 客户端通过此首部提供认证信息

​ 响应

​ ETag: 内容的扩展标签

​ Location: 重定向后的新资源位置

​ Server: 服务器软件信息, 版本号

​ WWW-Authenticate: 要求对客户端进行认证(通常状态码为401)

​ Age: 用户所请求的内容从构建响应倒此刻为止使用的时间

​ 实体

​ Content-Encoding: 内容编码

​ Content-Language: 内容语言

​ Content-Lenth: 响应内容的长度

​ Content-Type: 内容的MIME格式

​ Expires: 过期时间

​ Last-Modified: 最后一次修改时间

​ Cache-Control: 缓存控制

Varnish:

​ web缓存, 代理服务器.

varnish主要运行两个进程: Management进程和Child进程(也叫Cache进程).

Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。

状态引擎

​ 子例程, 函数, 可以使用return()函数返回状态给varnish

​ vcl_recv, vcl_pass, vcl_hash, vcl_pipe

​ vcl_hash: vcl_hit, vcl_miss

​ vcl_pass: vcl_fetch

​ vcl_hit: vcl_deliver, vcl_pass

​ vcl_miss: vcl_fetch, vcl_pass

​ vcl_fetch: vcl_deliver

Varnish安装

yum install readline-devel
yum install ncurses-devel
cd varnish-3.0.0
./autogen.sh
./configure --prefix=/usr/local/varnish PKG_CONFIG_PATH=/usr/lib/pkgconfig
 
make
make install

配置控制

修改配置/etc/sysconfig/varnish

VARNISH_LISTEN_PORT=80
VARNISH_STORAGE_FILE="malloc,100M"

连接本地管理接口

varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082

查看本地配置

vcl.list

查看配置内容

vcl.show [name]

eg.

vcl.load test1 /etc/varnish/test.vcl
200 13
VCL compiled.
vcl.list
200 47
active          1 boot
available       0 test1

vcl.use test1
200 0

vcl.show test1
200 59
backend websrv1 {
  .host="172.16.100.12";
  .port="80";
}

test.vcl

backend web1 {
  .host="172.16.100.12";
  .port="80";
  .probe = {
    .url = "/index.html";
    .window = 5;
    .threshold = 2;
    .interval = 3s;
  }
}

backend web2 {
  .host = "172.16.100.13";
  .port = "80";
}

#director websrvs random {
#  {
#    .backend = web1;
#    .weight = 2;
#  }
#  {
#    .backend = web2;
#    .weight = 1;
#  }
#}


acl purgers {
  "127.0.0.1";
  "192.168.48.0"/24;
  }

sub vcl_recv {
  if (req.url ~ "\.(html|css|js)$") {
    set req.backend = web2;
  } else {
    set req.backend = web1;
  }
#  set req.backend = websrvs;
  if (req.request == "PURGE") {
    if (!client.ip ~ purgers) {
      error 405 "Method not allowed";
    }
  }

  if (req.url ~ "test.html") {
    return(pass);
  }
  return(lookup);
}
sub vcl_hit {
  if (req.request == "PURGE") {
    purge;
    error 200 "Purged OK.";
  }
}

sub vcl_miss {
  if (req.request == "PURGE") {
    purge;
    error 404 "Not in cache";
  }
}

sub vcl_pass {
  if (req.request == "PURGE") {
    error 502 "Purged on a passed object.";
  }
}

sub vcl_fetch {
  if (req.url ~ "\.(jpg|jpeg|gif|png)$") {
    set beresp.ttl = 7200s;
  }

  if (req.url ~ "\.(html|css|js)$") {
    set beresp.ttl = 1299s;
  }
}

sub vcl_deliver {
  if (obj.hits > 0) {
    set resp.http.X-Cache = "HIT from " + server.ip;
  } else {
    set resp.http.X-Cache = "MISS";
  }
}

req.restarts: 重新启动检查次序

使用PURGE方法去除缓存

 curl -X PURGE http://192.168.48.131/index.htmlxxxxxxxxxx curl -X PURGE 

 

TOMCAT

动态站点:

​ 运行程序

​ 服务器端: CGI common gateway interface

​ 客户端:

applet:应用小程序

java技术的组成部分:

​ 1 . java程序设计语言, 依赖于API开发

​ 2 . java API

​ 3 . java 虚拟机

​ 4 . java class文件格式规范

java的编译时环境:

​ 源代码: .java

​ a.java, b.java, c.java --> Java编译器(javac)--> a.class, b.class, c.class(字节码)

java的运行时环境:

​ a.class, b.class, c.class --> JVM <-- Object.class, String.class, ...

java VM的组成部分:

​ java class loader (Java类加载器) : jar 打包格式

​ java执行引擎(执行环境)

java语言的特性:

​ 面向对象: 数据+方法

​ 多线程编程: 适用于并行架构(多核心架构), 实现程序的高效执行

​ 垃圾收集: Garbage Collector

​ 动态链接: 数据被引用次数为0则可以被GC回收

​ 动态扩展

android: java + jvm + Linux

ios: Object-C + FreeBSD

Java的发展历史

1995年5月23日,Java语言诞生 1996年1月,第一个JDK-JDK1.0诞生 1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入JAVA技术 1996年9月,约8.3万个网页应用了JAVA技术来制作 1997年2月18日,JDK1.1发布 1997年4月2日,JavaOne会议召开,参与者逾一万人,创当时全球同类会议规模之纪录 1997年9月,JavaDeveloperConnection社区成员超过十万 1998年2月,JDK1.1被下载超过2,000,000次 1998年12月8日,JAVA2企业平台J2EE发布 1999年6月,SUN公司发布Java的三个版本:标准版(JavaSE,以前是J2SE)、企业版(JavaEE以前是J2EE)和微型版(JavaME,以前是J2ME) 2000年5月8日,JDK1.3发布 2000年5月29日,JDK1.4发布 2001年6月5日,NOKIA宣布,到2003年将出售1亿部支持Java的手机 2001年9月24日,J2EE1.3发布 2002年2月26日,J2SE1.4发布,自此Java的计算能力有了大幅提升 2004年9月30日18:00PM,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE1.5更名为Java SE 5.0 2005年6月,JavaOne大会召开,SUN公司公开Java SE 6。此时,Java的各种版本已经更名,以取消其中的数字“2”:J2EE更名为Java EE,J2SE更名为Java SE,J2ME更名为Java ME 2006年12月,SUN公司发布JRE6.0 2009年4月7日Google App Engine开始支持Java 2009年04月20日,甲骨文74亿美元收购Sun。取得java的版权。 2010年11月,由于甲骨文对于Java社区的不友善,因此Apache扬言将退出JCP。 2011年7月28日,甲骨文发布java7.0的正式版。 2014年3月19日,甲骨文公司发布java8.0的正式版。

主要服务

1.JDBC(Java Database Connectivity)提供连接各种关系数据库的统一接口,作为数据源,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯Java API 编写数据库应用程序,同时,JDBC也是个商标名。 2.EJB(Enterprise JavaBeans)使得开发者方便地创建、部署和管理跨平台的基于组件的企业应用。 3.Java RMI(Java Remote Method Invocation)用来开发分布式Java应用程序。一个Java对象的方法能被远程Java虚拟机调用。这样,远程方法激活可以发生在对等的两端,也可以发生在客户端和服务器之间,只要双方的应用程序都是用Java写的。 4.Java IDL(Java Interface Definition Language) 提供与CORBA(Common Object Request Broker Architecture)的无缝的互操作性。这使得Java能集成异构的商务信息资源。 5.JNDI(Java Naming and Directory Interface)提供从Java平台到的统一的无缝的连接。这个接口屏蔽了企业网络所使用的各种命名和目录服务。 6.JMAPI(Java Management API)为异构网络上系统、网络和服务管理的开发提供一整套丰富的对象和方法。 7.JMS(Java Message Service)提供企业消息服务,如可靠的消息队列、发布和订阅通信、以及有关推拉(Push/Pull)技术的各个方面。 8.JTS(Java transaction Service)提供存取事务处理资源的开放标准,这些事务处理资源包括事务处理应用程序、事务处理管理及监控。 9.JMF(Java Media Framework API),她可以帮助开发者把音频、视频和其他一些基于时间的媒体放到Java应用程序或applet小程序中去,为多媒体开发者提供了捕捉、回放、编解码等工具,是一个弹性的、跨平台的多媒体解决方案。 10.Annotation(Java Annotation),在已经发布的JDK1.5(tiger)中增加新的特色叫Annotation。Annotation提供一种机制,将程序的元素如:类,方法,属性,参数,本地变量,包和元数据联系起来。这样编译器可以将元数据存储在Class文件中。这样虚拟机和其它对象可以根据这些元数据来决定如何使用这些程序元素或改变它们的行为。 在Java技术中,值得关注的还有JavaBeans,它是一个开放的标准的组件体系结构,它独立于平台,但使用Java语言。一个JavaBean是一个满足JavaBeans规范的Java类,通常定义了一个现实世界的事物或概念。一个JavaBean的主要特征包括属性、方法和事件。通常,在一个支持JavaBeans规范的开发环境(如Sun Java Studio 和IBM VisualAge for Java)中,可以可视地操作JavaBean,也可以使用JavaBean构造出新的JavaBean。JavaBean的优势还在于Java带来的可移植性。EJB (Enterprise JavaBeans) 将JavaBean概念扩展到Java服务端组件体系结构,这个模型支持多层的分布式对象应用。除了JavaBeans,典型的组件体系结构还有DCOM和CORBA,关于这些组件体系结构的深入讨论超出了本书的范围。 11.javaFX Sun刚刚发布了JavaFX技术的正式版,它使您能利用JavaFX 编程语言开发富互联网应用程序(RIA)。JavaFX Script编程语言(以下称为JavaFX)是Sun微系统公司开发的一种declarative,staticallytyped(声明性的、静态类型)脚本语言。JavaFX技术有着良好的前景,包括可以直接调用Java API的能力。因为JavaFXScript是静态类型,它同样具有结构化代码、重用性和封装性,如包、类、继承和单独编译和发布单元,这些特性使得使用Java技术创建和管理大型程序变为可能。 JavaFX从它2007年发布以来,表现一直差强人意。Oracle收购了Sun之后,在JavaFX中投入了大量的精力进行推广和更新。JavaFX比较出名的应用应该是在2010年温哥华冬奥会上,调整了JavaFX中的很多概念,以及重新设计和实现了很多重要组件之后,得到的就是现在的JavaFX 2.0。JavaFX 2.0的beta版已经发布,正式版则定于2010年第3季度发布。JavaFX 2.0的新特性使得开发人员应该需要重新审视它在RIA开发领域中的位置。在很多情况下,JavaFX 2.0也会是不错的选择。 12.JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入 管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝 集成的系统、网络和服务管理应用。 13.JPA(Java Persistence API),JPA通过JDK 5.0注解或XML(标准通用标记语言的子集)描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 14.JSP(Java Server Pages)是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML文件(.htm,.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件(*.jsp)。 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。

Java环境

.java --> javac --> .class

JRE: Java Running Environment

​ 由JVM(Hotspot) + JavaSE API

JDK: JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库。

​ Java程序设计语言

​ 工具及工具API

​ JRE

Java SE: Standard Edtion, J2SE. 支持面向桌面级应用, 提供完整的Java核心API

Java EE: Enterprise Edition, J2EE 支持使用多层次架构的企业应用(如EJB, CRM等), 包含了Java SE, 并额外提供了大量企业级别的类库.

Java ME: Micro Edition, J2ME. 轻量级Java

方法区--->堆--->栈--->PC寄存机器--->本地方法栈

堆区域: 存放对象

CGI: 在服务器端进行运行脚本

servlet container: servlet 容器

html必须硬编码在java代码中

jsp: java类,开发动态服务器应用程序的.依赖工具jasper, 将存在着嵌入在html文档中的程序整个整体转换为servlet代码. 直接使用<% %>直接嵌入在HTML文档中, jasper能够用于检测此html页面中的标记提取

<html>
	<%
	%>
</html>

JAVA EE Application Servers

Websphere: IBM提供, 几乎完全兼容企业级EE环境平台. %40. 过于重量级 Weblogic: BEA公司提供, 后被oracle收购. %30 oc4j: oracle提供 JBoss: Redhat开源 JOnAS Geronimo Glassfish

Tomcat: catalina Apache开发的前身 Jetty: 更轻量级, taobao使用 Resin: 仅供学习

JDK分类:

​ Oracle: JDK 不开源但是开放使用

​ Oracle: JRockit

​ Open: OpenJDK

稳定的JDK版本:

​ jdk-6u31

​ jdk-7u9

编译安装java环境

使用rpm安装jdk包, 到java的官网下载

配置java的home路径在/etc/profile.d/java.sh

export JAVA_HOME=/usr/java/latest
export PATH=$JAVA_HOME/bin:$PATH

查看总共运行多少个java程序

jps

Java 测试代码

public class Test{
	public static void main(String[] args){
		System.out.println("Hello,Welcome to MageEdu Linux Learning Center!");
	}
}

tomcat 3.x 初版

tomcat 4.0, Catelina

配置tomcat环境变量/etc/profile.d/tomcat.sh

export CATALINA_HOME=/usr/local/tomcat
export PATH=$CATALINA_HOME/bin:$PATH

查看tomcat版本

catalina.sh version

监测tomcat的配置语法

catalina.sh configtest

Tomcat配置层次

<Server
	<Service>
		<Connecter />	#简单组件
		<engine>
			<host>
				<context>
				</context>
			</host>
		</engine>
	</Service>
</Server>

顶级组件: 位于整个配置的最外层

容器类组件: 可以包含其他组件的组件

连接器组件: 连接用户请求至tomcat

被嵌套类的组件: 位于一个容器当中,不能包含其他组件

容器类:

​ engine: 核心容器, tomcat真正提供jsp解析转换并提供服务的组件. catalina引擎, 负责通过connector接受用户请求, 分析请求并处理请求. 引擎内的 可以有多个.

​ host: 类似于httpd中的虚拟主机, 一般而言支持基于FQDN的虚拟主机

​ context: 最内层的容器类组件, 一个context通常代表一个webapp; 配置context的主要目的,指定对应的webapp的根目录, 还能为webapp指定额外的属性, 如部署方式等

部署: 使用类加载器, 为webapp准备好其依赖的所有类;

服务类:

​ service: 将连接器关联至engine; 一个service内部可以有多个连接器,但是职能有一个engine

顶级组件: server, 表示一个运行与JVM中的tomcat实例;

嵌套类组件:

​ valve: 拦截请求并在将其转至对应的webapp之前进行某种处理操作; 可以用于任何容器中

​ access log valve: 访问日志

​ remote address filter value: 基于IP做访问控制

​ logger: 日志记录器, 用于记录组件内部的状态信息

​ 可用于除context之外的任何容器之中

​ realm: 关联一个用户认证库, 实现认证和授权, 可以用于任何容器类的组件中.

​ UserDatabaseRealm: 使用JNDI自定义的用户认证库

​ MemoryRealm: tomcat-users.xml中

​ JDBCRealm: 基于JDBC连接至数据库中查找用户

apache jserv protocol: 为一种二进制协议, 使用httpd反向代理用户请求至tomcat时, 在httpd和tomcat之间使用.

Tomcat sysV 服务脚本
#!/bin/sh
# Tomcat init script for Linux.
#
# chkconfig: 2345 96 14
# description: The Apache Tomcat servlet/JSP container.
JAVA_HOME=/usr/java/latest
CATALINA_HOME=/usr/local/tomcat
export JAVA_HOME CATALINA_HOME
case $1 in
start)
        exec $CATALINA_HOME/bin/catalina.sh start ;;
stop)
        exec $CATALINA_HOME/bin/catalina.sh stop ;;
restart)
        $CATALINA_HOME/bin/catalina.sh stop
        sleep 2
        exec $CATALINA_HOME/bin/catalina.sh start ;;
*)
        exec $CATALINA_HOME/bin/catalina.sh $1 ;;
esac

Tomcat 常见组件

1、服务器(server):Tomcat的一个实例,通常一个JVM只能包含一个Tomcat实例;因此,一台物理服务器上可以在启动多个JVM的情况下在每一个JVM中启动一个Tomcat实例,每个实例分属于一个独立的管理端口。这是一个顶级组件。 2、服务(service):一个服务组件通常包含一个引擎和与此引擎相关联的一个或多个连接器。给服务命名可以方便管理员在日志文件中识别不同服务产生的日志。一个server可以包含多个service组件,但通常情下只为一个service指派一个server。

连接器类组件: 3、连接器(connectors):负责连接客户端(可以是浏览器或Web服务器)请求至Servlet容器内的Web应用程序,通常指的是接收客户发来请求的位置及服务器端分配的端口。默认端口通常是HTTP协议的8080,管理员也可以根据自己的需要改变此端口。一个引擎可以配置多个连接器,但这些连接器必须使用不同的端口。默认的连接器是基于HTTP/1.1的Coyote。同时,Tomcat也支持AJP、JServ和JK2连接器。

容器类组件: 4、引擎(Engine):引擎通是指处理请求的Servlet引擎组件,即Catalina Servlet引擎,它检查每一个请求的HTTP首部信息以辨别此请求应该发往哪个host或context,并将请求处理后的结果返回的相应的客户端。严格意义上来说,容器不必非得通过引擎来实现,它也可以是只是一个容器。如果Tomcat被配置成为独立服务器,默认引擎就是已经定义好的引擎。而如果Tomcat被配置为Apache Web服务器的提供Servlet功能的后端,默认引擎将被忽略,因为Web服务器自身就能确定将用户请求发往何处。一个引擎可以包含多个host组件。 5、主机(Host):主机组件类似于Apache中的虚拟主机,但在Tomcat中只支持基于FQDN的“虚拟主机”。一个引擎至少要包含一个主机组件。 6、上下文(Context):Context组件是最内层次的组件,它表示Web应用程序本身。配置一个Context最主要的是指定Web应用程序的根目录,以便Servlet容器能够将用户请求发往正确的位置。Context组件也可包含自定义的错误页,以实现在用户访问发生错误时提供友好的提示信息。

被嵌套类(nested)组件: 这类组件通常包含于容器类组件中以提供具有管理功能的服务,它们不能包含其它组件,但有些却可以由不同层次的容器各自配置。 7、阀门(Valve):用来拦截请求并在将其转至目标之前进行某种处理操作,类似于Servlet规范中定义的过滤器。Valve可以定义在任何容器类的组件中。Valve常被用来记录客户端请求、客户端IP地址和服务器等信息,这种处理技术通常被称作请求转储(request dumping)。请求转储valve记录请求客户端请求数据包中的HTTP首部信息和cookie信息文件中,响应转储valve则记录响应数据包首部信息和cookie信息至文件中。 8、日志记录器(Logger):用于记录组件内部的状态信息,可被用于除Context之外的任何容器中。日志记录的功能可被继承,因此,一个引擎级别的Logger将会记录引擎内部所有组件相关的信息,除非某内部组件定义了自己的Logger组件。 9、领域(Realm):用于用户的认证和授权;在配置一个应用程序时,管理员可以为每个资源或资源组定义角色及权限,而这些访问控制功能的生效需要通过Realm来实现。Realm的认证可以基于文本文件、数据库表、LDAP服务等来实现。Realm的效用会遍及整个引擎或顶级容器,因此,一个容器内的所有应用程序将共享用户资源。同时,Realm可以被其所在组件的子组件继承,也可以被子组件中定义的Realm所覆盖。

引擎(Engine):引擎是指处理请求的Servlet引擎组件,即Catalina Servlet引擎,它从HTTPconnector接收请求并响应请求。它检查每一个请求的HTTP首部信息以辨别此请求应该发往哪个host或context,并将请求处理后的结果返回的相应的客户端。严格意义上来说,容器不必非得通过引擎来实现,它也可以是只是一个容器。如果Tomcat被配置成为独立服务器,默认引擎就是已经定义好的引擎。而如果Tomcat被配置为Apache Web服务器的提供Servlet功能的后端,默认引擎将被忽略,因为Web服务器自身就能确定将用户请求发往何处。一个引擎可以包含多个host组件。

连接器属性

定义连接器可以使用多种属性,有些属性也只适用于某特定的连接器类型。一般说来,常见于server.xml中的连接器类型通常有4种: 1) HTTP连接器 2) SSL连接器 3) AJP 1.3连接器 4) proxy连接器

<Connector port="8080" protocol="HTTP/1.1"
      maxThreads="150" connectionTimeout="20000"
      redirectPort="8443"/>

定义连接器时可以配置的属性非常多,但通常定义HTTP连接器时必须定义的属性只有“port”,定义AJP连接器时必须定义的属性只有"protocol",因为默认的协议为HTTP。以下为常用属性的说明: 1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0; 2) maxThreads:支持的最大并发连接数,默认为200; 3) port:监听的端口,默认为0; 4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3; 5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口; 6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟; 7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;

<Connector port="8443"
    maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
    enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true"
    clientAuth="false" sslProtocol="TLS" />
Engine组件

Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。Engine需要defaultHost属性来为其定义一个接收所有发往非明确定义虚拟主机的请求的host组件。如前面示例中定义的:

常用的属性定义: defaultHost:Tomcat支持基于FQDN的虚拟主机,这些虚拟主机可以通过在Engine容器中定义多个不同的Host组件来实现;但如果此引擎的连接器收到一个发往非非明确定义虚拟主机的请求时则需要将此请求发往一个默认的虚拟主机进行处理,因此,在Engine中定义的多个虚拟主机的主机名称中至少要有一个跟defaultHost定义的主机名称同名; name:Engine组件的名称,用于日志和错误信息记录时区别不同的引擎;

Engine容器中可以包含Realm、Host、Listener和Valve子容器。

Host组件

位于Engine容器中用于接收请求并进行相应处理的主机或虚拟主机,如前面示例中的定义:

  <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
  </Host>

常用属性说明: 1) appBase:此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径;可以使用基于$CATALINA_HOME的相对路径; 2) autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true; 3) unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;

<Engine name="Catalina" defaultHost="localhost">
  <Host name="localhost" appBase="webapps">
    <Context path="" docBase="ROOT"/>
    <Context path="/bbs" docBase="/web/bss"
      reloadable="true" crossContext="true"/>
  </Host>
  
  <Host name="mail.magedu.com" appBase="/web/mail">
    <Context path="" docBase="ROOT"/>
  </Host>
</Engine>

主机别名定义: 如果一个主机有两个或两个以上的主机名,额外的名称均可以以别名的形式进行定义,如下:

<Host name="www.magedu.com" appBase="webapps" unpackWARs="true">
  <Alias>magedu.com</Alias>
</Host>
Context组件

Context在某些意义上类似于apache中的路径别名,一个Context定义用于标识tomcat实例中的一个Web应用程序;如下面的定义:

<!-- Tomcat Root Context -->
<Context path="" docBase="/web/webapps"/>

<!-- buzzin webapp -->
<Context path="/bbs"
  docBase="/web/threads/bbs"
  reloadable="true">
</Context>

<!-- chat server -->
  <Context path="/chat" docBase="/web/chat"/>
  
<!-- darian web -->
<Context path="/darian" docBase="darian"/>

在Tomcat6中,每一个context定义也可以使用一个单独的XML文件进行,其文件的目录为$CATALINA_HOME/conf//。可以用于Context中的XML元素有Loader,Manager,Realm,Resources和WatchedResource。

常用的属性定义有: 1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字; 2) path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;如果context定义在一个单独的xml文件中,此属性不需要定义; 3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false

Realm组件

一个Realm表示一个安全上下文,它是一个授权访问某个给定Context的用户列表和某用户所允许切换的角色相关定义的列表。因此,Realm就像是一个用户和组相关的数据库。定义Realm时惟一必须要提供的属性是classname,它是Realm的多个不同实现,用于表示此Realm认证的用户及角色等认证信息的存放位置。 JAASRealm:基于Java Authintication and Authorization Service实现用户认证; JDBCRealm:通过JDBC访问某关系型数据库表实现用户认证; JNDIRealm:基于JNDI使用目录服务实现认证信息的获取; MemoryRealm:查找tomcat-user.xml文件实现用户信息的获取; UserDatabaseRealm:基于UserDatabase文件(通常是tomcat-user.xml)实现用户认证,它实现是一个完全可更新和持久有效的MemoryRealm,因此能够跟标准的MemoryRealm兼容;它通过JNDI实现;

下面是一个常见的使用UserDatabase的配置: <Realm className=”org.apache.catalina.realm.UserDatabaseRealm”

resourceName=”UserDatabase”/>

下面是一个使用JDBC方式获取用户认证信息的配置: <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"

driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost/authority"
connectionName="test" connectionPassword="test"
userTable="users" userNameCol="user_name"
userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />
Valve组件

Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。Tomcat6中实现了多种不同的Valve: AccessLogValve:访问日志Valve ExtendedAccessValve:扩展功能的访问日志Valve JDBCAccessLogValve:通过JDBC将访问日志信息发送到数据库中; RequestDumperValve:请求转储Valve; RemoteAddrValve:基于远程地址的访问控制; RemoteHostValve:基于远程主机名称的访问控制; SemaphoreValve:用于控制Tomcat主机上任何容器上的并发访问数量; JvmRouteBinderValve:在配置多个Tomcat为以Apache通过mod_proxy或mod_jk作为前端的集群架构中,当期望停止某节点时,可以通过此Valve将用记请求定向至备用节点;使用此Valve,必须使用JvmRouteSessionIDBinderListener; ReplicationValve:专用于Tomcat集群架构中,可以在某个请求的session信息发生更改时触发session数据在各节点间进行复制; SingleSignOn:将两个或多个需要对用户进行认证webapp在认证用户时连接在一起,即一次认证即可访问所有连接在一起的webapp; ClusterSingleSingOn:对SingleSignOn的扩展,专用于Tomcat集群当中,需要结合ClusterSingleSignOnListener进行工作;

RemoteHostValve和RemoteAddrValve可以分别用来实现基于主机名称和基于IP地址的访问控制,控制本身可以通过allow或deny来进行定义,这有点类似于Apache的访问控制功能;如下面的Valve则实现了仅允许本机访问/probe:

<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.0\.0\.1"/>

 

其中相关属性定义有: 1) className:相关的java实现的类名,相应于分别应该为org.apache.catalina.valves.RemoteHostValve或org.apache.catalina.valves.RemoteAddrValve; 2) allow:以逗号分开的允许访问的IP地址列表,支持正则表达式,因此,点号“.”用于IP地址时需要转义;仅定义allow项时,非明确allow的地址均被deny; 3) deny: 以逗号分开的禁止访问的IP地址列表,支持正则表达式;使用方式同allow;

GlobalNamingResource

应用于整个服务器的JNDI映射,此可以避免每个Web应用程序都需要在各自的web.xml创建,这在web应用程序以WAR的形式存在时尤为有用。它通常可以包含三个子元素: 1) Environment; 2) Resource; 3) ResourceEnvRef;

其他组件

WatchedResource

WatchedResource可以用于Context中监视指定的webapp程序文件的改变,并且能够在监视到文件内容发生改变时重新装载此文件。

Listener

Listener用于创建和配置LifecycleListener对象,而LifecycleListener通常被开发人员用来创建和删除容器。

Loader

Java的动态装载功能是其语言功能强大表现之一,Servlet容器使用此功能在运行时动态装载servlet和它们所依赖的类。Loader可以用于Context中控制java类的加载。

Stores

PersistentManager必须包含一个Store元素以指定将会话数据存储至何处。这通常有两种实现方式:FileStore和JDBCStore。

Resources

经常用于实现在Context中指定需要装载的但不在Tomcat本地磁盘上的应用资源,如Java类,HTML页面,JSP文件等。

Cluster

专用于配置Tomcat集群的元素,可用于Engine和Host容器中。在用于Engine容器中时,Engine中的所有Host均支持集群功能。在Cluster元素中,需要直接定义一个Manager元素,这个Manager元素有一个其值为org.apache.catalina.ha.session.DeltaManager或org.apache.catalina.ha.session.BackupManager的className属性。同时,Cluster中还需要分别定义一个Channel和ClusterListener元素。

Channel

用于Cluster中给集群中同一组中的节点定义通信“信道”。Channel中需要至少定义Membership、Receiver和Sender三个元素,此外还有一个可选元素Interceptor

Membership

用于Channel中配置同一通信信道上节点集群组中的成员情况,即监控加入当前集群组中的节点并在各节点间传递心跳信息,而且可以在接收不到某成员的心跳信息时将其从集群节点中移除。Tomcat6中Membership的实现是org.apache.catalina.tribes.membership.McastService。

Sender

用于Channel中配置“复制信息”的发送器,实现发送需要同步给其它节点的数据至集群中的其它节点。发送器不需要属性的定义,但可以在其内部定义一个Transport元素。

Transport

用于Sender内部,配置数据如何发送至集群中的其它节点。Tomcat6有两种Transport的实现: 1) PooledMultiSender 基于Java阻塞式IO,可以将一次将多个信息并发发送至其它节点,但一次只能传送给一个节点。 2)PooledParallelSener 基于Java非阻塞式IO,即NIO,可以一次发送多个信息至一个或多个节点。

Receiver

用于Channel定义某节点如何从其它节点的Sender接收复制数据,Tomcat6中实现的接收方式有两种BioReceiver和NioReceiver。

WEB.xml文件

web.xml基于Java Servlet规范,可被用于每一个Java servlet容器,通常有两个存放位置,$CATALINA_BASE/conf和每个Web应用程序(通常是WEB-INF/web.xml)。Tomcat在deploy一个应用程序时(包括重启或重新载入),它首先读取conf/web.xml,而后读取WEB-INF/web.xml。

tomcat自带管理器

tomcat自带两个管理类的app

​ server status:

​ 获取状态信息

​ 部署应用程序

​ host manager

​ 管理虚拟主机

http://www.jspxcms.com/

tomcat架构实现

Tomcat: JDK + servlet, jsp 是一种Java EE不完整的实现

server.xml

​ 顶级类: server

​ 容器类: engine, host, context

​ 服务类: service

​ 连接器: connector

​ http, ssl, ajp (apache jserv protocol)

​ 被嵌套类: valve, logger, realm

<server>
	<service>
		<connector />
		<connector />
		<engine>
			<host>
				<context />
				<context />
			</host>
			<host>
			</host>
		</engine>
	</service>
</server>

Tomcat的配置文件

​ server.xml

​ context.xml: 为部署于此Tomcat实例上的所有web应用程序提供的默认配置文件,每个webapp都可以使用独有的context.xml, 通常放置于webapp目录中的META-INF子目录中; 常用于定义会话管理器, Realm以及JDBC等

​ web.xml: 为部署于此tomcat实例上的所有web应用程序提供默认部署描述符. 通常用于为webapp提供基本的servlet定义和MIME映射表等;

​ tomcat-uesrs.xml: 管理权限

​ calalina.policy: 当基于 -security选项启动tomcat实例时会读取此配置文件, 此文件为JAVA的安全策略配置文件, 配置访问codebase或某些Java类的权限

​ catalina.properties: Java属性定义文件, 设定类加载器路径, 安全包列表和一些调整性能的参数信息

​ logging.properties: 定义日志相关的配置信息, 如日志级别, 文件路径等

Tomcat 应用程序"部署"

​ 部署是指将webapp及其所依赖类库等装载进tomcat实例上, 以便接受用户请求. 部署方式:

​ 静态方式: 在tomcat启动之前进行的webapp部署

​ 动态方式: 在不打断tomcat运行的前提下, 通过tomcat manager或其他命令行工具进行部署

​ TCD: Tomcat Client Deployer

​ 部署是由一类"操作"组成:

​ Deploy: 将webapp的源文件放置于目标目录, 配置tomcat服务器能够基于context路径访问webapp, 并将其特有的类装载进行装载等;

​ Redeploy: 重新部署, 主要用于升级时;

​ Undeploy: 取消部署, 停止应用程序并移除并从tomcat实例上移除其部分文件和部署名等;

​ stop: 停止

​ start: 将停止的webapp启动起来

​ 部署方式:

​ Tomcat Manager

​ ANT 脚本

​ TCD

​ war类归档程序的部署, 将归档文件复制到$CATALINA_BASE/webapps/目录中, 并重启tomcat即可. tomcat会自动展开war归档.

webapp体系结构:

​ webapp有特定的组织格式, 是一种层次型目录结构:通常包含了servlet代码文件, jsp页面文件, 类文件, 部署描述符文件等, 一般会打包成归档格式

​ /: web应用程序的根目录(documentRoot)

​ /WEB-INF: 此webapp的私有资源目录, 通常web.xml和context.xml均放置在此处

​ /WEB-INF/classes: 此webapp自有的类

​ /WEB-INF/lib: 此webapp自有的能够被打包为jar格式的类

​ /META-INF/: 也是私有区域

webapp的归档格式:

​ EJB类归档的扩展名为.jar

​ web应用程序的归档扩展名为.war

​ 资源适配器的扩展名resource adapters .rar

​ 企业级应用程序的扩展名.ear

​ web服务的扩展名为.ear或.war

Tomcat分离运行方式

standalone configure:

​ request --> web server(tomcat) --> servlet container

apache与tomcat连接器通信的模块有两个:

​ mod_jk: apache/1.3, apache /2.0

​ mod_proxy: apache/2.2+

tomcat的连接器协议有两种:

​ http

​ ajp

mod_jk V.S. mod_proxy:

​ 负载均衡

​ 管理接口

​ 兼容性

​ 配置: mod_proxy比较简单

​ 协议: mod_jk (ajp) , mod_proxy(http/https/ajp)

Tomcat的http连接器:

​ 类型有三种: 基于java的http/1.1连接器; 基于java的高性能NIO连接器; 基于C/C++研发的Native APR HTTP/1.1连接器

LNMT:

​ nginx + tomcat(http,https)

​ nginx + tomcat, ....

http{
  upstream tomcat {
  	server 192.168.48.131:8080;
  	server 192.168.48.132:8080;
	}
  server {
  	location ~* \.(jsp|do)$ {
  		proxy_pass http://tomcat;
		}
	}
}

LAMT:

​ apache可以使用(mod_jk, ajp) + tomcat(ajp connector)

​ apache可以使用(mod_proxy, (http,https,ajp) + tomcat(http,https,ajp)

​ mod_proxy(http,https,ajp):

mod_proxy.conf

ProxyVia on
ProxyRequests off
ProxyPreserveHost on

ProxyPass / ajp://192.168.48.131:8009/
ProxyPassReverse / ajp://192.168.48.131:8009/

<Location />
	Order Allow,Deny
	Allow from all
</Location>

使用jk_mod

LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/httpd/conf.d/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel  debug
JkMount /* TomcatA
JkMount /status/ statA

workers.properties

worker.list=TomcatA,statA
worker.TomcatA.port=8009
worker.TomcatA.type=ajp13
worker.TomcatA.host=192.168.48.131
worker.TomcatA.lbfactor=1
worker.statA.type=status
LB LAMT

mod_jk的实现方式

workers.properties

worker.list=lbcA,statA
worker.TomcatA.port=8009
worker.TomcatA.type=ajp13
worker.TomcatA.host=192.168.48.131
worker.TomcatA.lbfactor=1
worker.TomcatB.port=8009
worker.TomcatB.type=ajp13
worker.TomcatB.host=192.168.48.137
worker.TomcatB.lbfactor=1

worker.lbcA.type=lb
worker.lbcA.sticky_session=0
worker.lbcA.balance_workers=TomcatA,TomcatB

worker.statA.type=status

mod_jk

LoadModule jk_module modules/mod_jk.so
JkWorkersFile /etc/httpd/conf.d/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel  notice
JkMount /* lbcA
JkMount /status/ statA

mod_proxy的实现方式

mod_proxy.conf

ProxyVia on
ProxyRequests off
ProxyPreserveHost on
<proxy balancer://lb>
    BalancerMember http://192.168.48.131:80 loadfactor=1 route=TomcatA
    BalancerMember http://192.168.48.137:80 loadfactor=1 route=TomcatB
</Proxy>

ProxyPass / balancer://lb/ stickysession=JSESSIONID
ProxyPassReverse / balancer://lb/

<Location />
    Order Allow,Deny
    Allow from all
</Location>

note: 负载均衡, 且实现会话绑定要注意给每个tomcat实例的engine容器一个jvmRoute属性, 此名称要跟前段调度模块中使用的名称保持一致. 另外, 在mod_proxy实现负载均衡的会话绑定时, 还要使用sticksession=JESSIONID(字符必须大写)

<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA">

Tomcat会话管理

Manager

1) StandardManager Tomcat6的默认会话管理器,用于非集群环境中对单个处于运行状态的Tomcat实例会话进行管理。当Tomcat关闭时,这些会话相关的数据会被写入磁盘上的一个名叫SESSION.ser的文件,并在Tomcat下次启动时读取此文件。 2) PersistentManager 当一个会话长时间处于空闲状态时会被写入到swap会话对象,这对于内存资源比较吃紧的应用环境来说比较有用。 3)DeltaManager 用于Tomcat集群的会话管理器,它通过将改变了会话数据同步给集群中的其它节点实现会话复制。这种实现会将所有会话的改变同步给集群中的每一个节点,也是在集群环境中用得最多的一种实现方式。 4)BackupManager 用于Tomcat集群的会话管理器,与DeltaManager不同的是,某节点会话的改变只会同步给集群中的另一个而非所有节点。 5)SimpleTcpReplicationManager Tomcat4时用到的版本,过于老旧了。

Tomcat Session集群

构建DeltaManager集群步骤

只适合极小规模的tomcat集群中

1 . 在各节点的server.xml的engine或host容器添加如上内容: 注意修改MemberShip组件中的多播地址address="228.0.0.4", 建议修改Receiver中的address为本机能够传递心跳信息的地址:

2 . 在各节点为使用组播地址添加路由, 格式为:

route add -net $MCAST_ADDRESS netmask 255.255.255.255 dev eth0

3 . 在相应应用程序的web.xml中添加<distributable/>

基于DelaManager或者BackupManager内存级别的会话同步

在server.xml配置文件的Engine组件中添加Cluster组件

        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="auto"
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>
memcached-session-manager

专用的会话服务器. 适合大规模集群

实现方法...

JVM调优

线程共享内存 (可调优)

​ 方法区: 存储jvm加载的class, 常量, 静态变量, 即时编译器编译后的代码等

​ java堆: 存储java的所有对象实例, 数组等

线程私有内存

​ 程序计数寄存器: 每个线程有自己的计数寄存器, 存储当前程序执行字节码地址

​ jvm栈: jvm会为每个运行线程分配一个栈区, 线程调用方法和方法返回时会进行入栈和出站操作

​ 本地方法栈区: 与jvm stack类似,只不过此区域是为调用本地方法服务

jinfo

-Xmx: 设置最大堆大小

-xms: 定义堆内存大小

-XX: Newsize (to, from, eden)

-XX: Maxnewsize 在堆内存内部如何分配使用的空间

-XX: PermSize

-XX: MaxPermSize

-XX: SuvivorRatio : Setting New heap size ratios

通过指定变量JAVA_OPTS

Mark-compact Better throughput

Incremental GC(Train) Better Pause

Parallel GC Best Throughput

Goncurrent GC Best Pause

Java性能查看工具

jconsole, visualvm, jprofiler, janalyzer

jstat 查看垃圾回收器的管理状态

jstat -gc 2023 1s

 

补充

if 判断语句

在location中使用if语句可以实现条件判断,其通常有一个return语句,且一般与有着last或break标记的rewrite规则一同使用。但其也可以按需要使用在多种场景下,需要注意的是,不当的使用可能会导致不可预料的后果。

syntax
if (condition){
  
}
location / {
	if ($request_method == “PUT”) {
		proxy_pass http://upload.magedu.com:8080;
	} 

	if ($request_uri ~ "\.(jpg|gif|jpeg|png)$") {
		proxy_pass http://imageservers;
		break;
	}
}

正则表达式匹配:

==: 等值比较;
~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
!~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
!~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;

文件及目录匹配判断:

-f, !-f:判断指定的路径是否为存在且为文件;
-d, !-d:判断指定的路径是否为存在且为目录;
-e, !-e:判断指定的路径是否存在,文件或目录均可;
-x, !-x:判断指定路径的文件是否存在且可执行;

WebDAV

web-based Distributed Auhoring and versioning, 一种基于HTTP 1.1协议的通信协议,它扩展了HTTP1.1, 在GET, POST, HEAD等几个HTTP标准方法以外添加了一些新的方法,使得应用程序可以直接对Web Server直接读写,并支持文件锁定(Locking)及解锁(Unlock), 还可以支持文件的版本控制

如果想让http web服务器允许上传和删除操作

LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
DocumentRoot "/var/www/html"
dav on;

httpwatch

IE的分析工具

libevent

项目主页: http://libevent.org/

算法复杂度

Big O: 评判数据结构复杂度

O(1): key value
O(logN): 弹性二叉树
O(n): 红黑二叉树
O(n^2)
O(2^n)

URL

URL: http(协议)://host:port/path?queries#fragment

://:@:/;?#

HTTP首部概览

HTTP首部概览:

1、 Accept:告诉WEB服务器自己接受什么介质类型,/ 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type。 2、 Accept-Charset: 浏览器申明自己接收的字符集 Accept-Encoding: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate) Accept-Language:浏览器申明自己接收的语言 语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等。 3、 Accept-Ranges:WEB服务器表明自己是否接受获取其某个实体的一部分(比如文件的一部分)的请求。bytes:表示接受,none:表示不接受。 4、 Age:当代理服务器用自己缓存的实体去响应请求时,用该头部表明该实体从产生到现在经过多长时间了。 5、 Authorization:当客户端接收到来自WEB服务器的 WWW-Authenticate 响应时,用该头部来回应自己的身份验证信息给WEB服务器。 6、 Cache-Control:请求:no-cache(不要缓存的实体,要求现在从WEB服务器去取) max-age:(只接受 Age 值小于 max-age 值,并且没有过期的对象) max-stale:(可以接受过去的对象,但是过期时间必须小于 max-stale 值) min-fresh:(接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象) 响应:public(可以用 Cached 内容回应任何用户) private(只能用缓存内容回应先前请求该内容的那个用户) no-cache(可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端) max-age:(本响应包含的对象的过期时间) ALL: no-store(不允许缓存) 7、 Connection:请求:close(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了)。 keepalive(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求)。 响应:close(连接已经关闭)。 keepalive(连接保持着,在等待本次连接的后续请求)。 Keep-Alive:如果浏览器请求保持连接,则该头部表明希望 WEB 服务器保持连接多长时间(秒)。例如:Keep-Alive:300 8、 Content-Encoding:WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。例如:Content-Encoding:gzip 9、Content-Language:WEB 服务器告诉浏览器自己响应的对象的语言。 10、Content-Length: WEB 服务器告诉浏览器自己响应的对象的长度。例如:Content-Length: 26012 11、Content-Range: WEB 服务器表明该响应包含的部分对象为整个对象的哪个部分。例如:Content-Range: bytes 21010-47021/47022 12、Content-Type: WEB 服务器告诉浏览器自己响应的对象的类型。例如:Content-Type:application/xml 13、ETag:就是一个对象(比如URL)的标志值,就一个对象而言,比如一个 html 文件,如果被修改了,其 Etag 也会别修改,所以ETag 的作用跟 Last-Modified 的作用差不多,主要供 WEB 服务器判断一个对象是否改变了。比如前一次请求某个 html 文件时,获得了其 ETag,当这次又请求这个文件时,浏览器就会把先前获得的 ETag 值发送给WEB 服务器,然后 WEB 服务器会把这个 ETag 跟该文件的当前 ETag 进行对比,然后就知道这个文件有没有改变了。 14、 Expired:WEB服务器表明该实体将在什么时候过期,对于过期了的对象,只有在跟WEB服务器验证了其有效性后,才能用来响应客户请求。是 HTTP/1.0 的头部。例如:Expires:Sat, 23 May 2009 10:02:12 GMT 15、 Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号。例如:Host:rss.sina.com.cn 16、 If-Match:如果对象的 ETag 没有改变,其实也就意味著对象没有改变,才执行请求的动作。 17、 If-None-Match:如果对象的 ETag 改变了,其实也就意味著对象也改变了,才执行请求的动作。 18、 If-Modified-Since:如果请求的对象在该头部指定的时间之后修改了,才执行请求的动作(比如返回对象),否则返回代码304,告诉浏览器 该对象没有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT 19、 If-Unmodified-Since:如果请求的对象在该头部指定的时间之后没修改过,才执行请求的动作(比如返回对象)。 20、 If-Range:浏览器告诉 WEB 服务器,如果我请求的对象没有改变,就把我缺少的部分给我,如果对象改变了,就把整个对象给我。浏览器通过发送请求对象的 ETag 或者 自己所知道的最后修改时间给 WEB 服务器,让其判断对象是否改变了。总是跟 Range 头部一起使用。 21、 Last-Modified:WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT 22、 Location:WEB 服务器告诉浏览器,试图访问的对象已经被移到别的位置了,到该头部指定的位置去取。例如:Location:http://i0.sinaimg.cn/dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif 23、 Pramga:主要使用 Pramga: no-cache,相当于 Cache-Control: no-cache。例如:Pragma:no-cache 24、 Proxy-Authenticate: 代理服务器响应浏览器,要求其提供代理身份验证信息。Proxy-Authorization:浏览器响应代理服务器的身份验证请求,提供自己的身份信息。 25、 Range:浏览器(比如 Flashget 多线程下载时)告诉 WEB 服务器自己想取对象的哪部分。例如:Range: bytes=1173546- 26、 Referer:浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得/点击 当前请求中的网址/URL。例如:Referer:http://www.sina.com/ 27、 Server: WEB 服务器表明自己是什么软件及版本等信息。例如:Server:Apache/2.0.61 (Unix) 28、 User-Agent: 浏览器表明自己的身份(是哪种浏览器)。例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2、0、0、14 29、 Transfer-Encoding: WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked)。例如:Transfer-Encoding: chunked 30、 Vary: WEB服务器用该头部的内容告诉 Cache 服务器,在什么条件下才能用本响应所返回的对象响应后续的请求。假如源WEB服务器在接到第一个请求消息时,其响应消息的头部为:Content- Encoding: gzip; Vary: Content-Encoding那么 Cache 服务器会分析后续请求消息的头部,检查其 Accept-Encoding,是否跟先前响应的 Vary 头部值一致,即是否使用相同的内容编码方法,这样就可以防止 Cache 服务器用自己 Cache 里面压缩后的实体响应给不具备解压能力的浏览器。例如:Vary:Accept-Encoding 31、 Via: 列出从客户端到 OCS 或者相反方向的响应经过了哪些代理服务器,他们用什么协议(和版本)发送的请求。当客户端请求到达第一个代理服务器时,该服务器会在自己发出的请求里面添 加 Via 头部,并填上自己的相关信息,当下一个代理服务器收到第一个代理服务器的请求时,会在自己发出的请求里面复制前一个代理服务器的请求的Via 头部,并把自己的相关信息加到后面,以此类推,当 OCS 收到最后一个代理服务器的请求时,检查 Via 头部,就知道该请求所经过的路由。例如:Via:1.0 236.D0707195.sina.com.cn:80 (squid/2.6.STABLE13)

 

Abbreviation

pv: page view 页面浏览量

RDP: Remote Desktop Protocol port 3389

 

 

 

 

 

 

 

 

 

 

 

posted on 2016-12-22 20:02  孙大喜 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/sundaxi/p/6212657.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值