Chinaunix首页 | 论坛 | 博客
  • 博客访问: 400814
  • 博文数量: 87
  • 博客积分: 2571
  • 博客等级: 少校
  • 技术积分: 920
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-29 13:10
文章分类

全部博文(87)

文章存档

2012年(49)

2011年(7)

2010年(26)

2009年(5)

分类: LINUX

2011-12-15 19:37:59

基于haproxy-1.4.18


疑问:
=======================================================================================
Q:后端server如何连接到proxy



Q:何时修改cookie
A:在各个协议解析类中,
如:proto_http.c的
int http_process_req_common(struct session *s, struct buffer *req, int an_bit, struct proxy *px)


使用场景:
=======================================================================================
haproxy和squid是两种不同的软件,
前者侧重于负载均衡(特别是应用负载),包括一些监测节点的机制,轻巧灵便使用简单,
后者侧重于代理和cache

lvs负载均衡属于4层应用,效率比HAPROXY的7层应用要高的多

当前,HAProxy支持两种主要的代理模式:"tcp"也即4层(大多用于邮件服务器、内部协议通信服务器等),和7层(HTTP)。
在4层模式下,HAproxy仅在客户端和服务器之间转发双向流量。
7层模式下,HAProxy会分析协议,并且能通过允许、拒绝、交换、增加、修改或者删除请求 (request)或者回应(response)里指定内容来控制协议,这种操作要基于特定规则。

轮叫调度(Round Robin Scheduling)算法就是以轮叫的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。
算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度


how it works(参考haproxy-1.4.18\doc\design-thoughts\how-it-works.txt)
=======================================================================================
For TCP and HTTP :
- listeners 建立 listening sockets,并将一个 READ callback 指向协议指定的accept()

- 协议指定的 accept() 接受连接,
  实例化一个 "server TCP socket" (which is dedicated to the client side),
  并配置其为 (non_block, get_original_dst, ...).

For TCP :
- 对纯粹的TCP,建立一个request buffer,和一个"client TCP
  socket", 用于连接the server.

- 一旦链接建立, 会分配一个 response buffer 并连接两端(connected to both ends)

- 两个 sockets 都设置为"autonomous mode", 因此当遇到特殊情况时(error or close),只会唤醒他们的supervising session 

For HTTP :
- 建立"HOLD" 标志的request buffer 和读限制,以支持header rewriting 
 (may be this one will be removed
  eventually because it's better to limit only to the buffer size and report
  an error when rewritten data overflows)


  
分发(参考doc/architecture.txt)
=======================================================================================
1.Simple HTTP load-balancing with cookie insertion
* haproxy依赖cookie中的SERVERID指定分发目标,
* 若没有该值,将选取一server
* 若原server掉线,将指定新server,并修改SERVERID值


步骤:
(client)                           (haproxy)                         (server A)
  >-- GET /URI1 HTTP/1.0 ------------> |
               ( no cookie, haproxy forwards in load-balancing mode. )
                                       | >-- GET /URI1 HTTP/1.0 ---------->
                                       | <-- HTTP/1.0 200 OK -------------<
               ( the proxy now adds the server cookie in return )
  <-- HTTP/1.0 200 OK ---------------< |
      Set-Cookie: SERVERID=A           |
  >-- GET /URI2 HTTP/1.0 ------------> |
      Cookie: SERVERID=A               |
      ( the proxy sees the cookie. it forwards to server A and deletes it )
                                       | >-- GET /URI2 HTTP/1.0 ---------->
                                       | <-- HTTP/1.0 200 OK -------------<
   ( the proxy does not add the cookie in return because the client knows it )
  <-- HTTP/1.0 200 OK ---------------< |
  >-- GET /URI3 HTTP/1.0 ------------> |
      Cookie: SERVERID=A               |
                                    ( ... )

局限:
1.proxy必须对SERVERID敏感,因此是单点
2.client可能禁止cookie,因此可能需要改用roundrobin方法,使来自相同IP的访问落到同一server,但该用法
不能用于嵌套proxy或小型网络


2. HTTP load-balancing with cookie prefixing and high availability
* 不新建cookie,使用已有的,在其中加入server的信息,如:
Set-Cookie: JSESSIONID=A~123  
  后续以JSESSIONID=A~123为标记分发该client的请求  
* 若client不带cookie,proxy不会跟踪其本次和后续请求,保持任意分发方式 
* 对单点问题:以1主1备的proxy,结合VRRP使用

步骤:
(client)                           (haproxy)                         (server A)
  >-- GET /URI1 HTTP/1.0 ------------> |
               ( no cookie, haproxy forwards in load-balancing mode. )
                                       | >-- GET /URI1 HTTP/1.0 ---------->
                                       |     X-Forwarded-For: 10.1.2.3
                                       | <-- HTTP/1.0 200 OK -------------<
                        ( no cookie, nothing changed )
  <-- HTTP/1.0 200 OK ---------------< |
  >-- GET /URI2 HTTP/1.0 ------------> |
    ( no cookie, haproxy forwards in lb mode, possibly to another server. )
                                       | >-- GET /URI2 HTTP/1.0 ---------->
                                       |     X-Forwarded-For: 10.1.2.3
                                       | <-- HTTP/1.0 200 OK -------------<
                                       |     Set-Cookie: JSESSIONID=123
    ( the cookie is identified, it will be prefixed with the server name )
  <-- HTTP/1.0 200 OK ---------------< |
      Set-Cookie: JSESSIONID=A~123     |
  >-- GET /URI3 HTTP/1.0 ------------> |
      Cookie: JSESSIONID=A~123         |
       ( the proxy sees the cookie, removes the server name and forwards
          to server A which sees the same cookie as it previously sent )
                                       | >-- GET /URI3 HTTP/1.0 ---------->
                                       |     Cookie: JSESSIONID=123
                                       |     X-Forwarded-For: 10.1.2.3
                                       | <-- HTTP/1.0 200 OK -------------<
                        ( no cookie, nothing changed )
  <-- HTTP/1.0 200 OK ---------------< |
                                    ( ... )

2.1 Variations involving external layer 4 load-balancers

session相关
======================================================================================
php.ini 里几个session相关值的 其它的值请参考《PHP与Mysql5程序设计》
session.use_cookies = 1  #表示 服务端和客户端交互session是通过cookie的方式 默认值
session.name = 9ai9     #默认值是PHPSESSID 我这里改成9ai9是为了和默认值区别
session.cache_limiter = nocache #此设置确保对每个请求,在可能提供缓存的版本前,
先请求发送到最初的服务器。这个值联系到下文中 cookie识别中的相关参数

haproxy三种方法保持客户端session一致
2.1 用户IP 识别   
haroxy 将用户IP经过hash计算后 指定到固定的真实服务器上(类似于nginx 的IP hash 指令)
配置指令        balance source
实例访问

2.2 cookie 识别  
haproxy 将WEB服务端发送给客户端的cookie中插入(或添加加前缀)haproxy定义的后端的服务器COOKIE ID。
配置指令例举  cookie  SESSION_COOKIE  insert indirect nocache
用firebug可以观察到用户的请求头的cookie里 
有类似" Cookie 9ai9=0bc588656ca05ecf7588c65f9be214f5; SESSION_COOKIE=12" SESSION_COOKIE=12就是haproxy添加的内容

2.3 session 识别  
haproxy 将后端服务器产生的session和后端服务器标识存在haproxy中的一张表里。客户端请求时先查询这张表。
配置指令例举 appsession 9ai9 len 64 timeout 5h request-learn 
注意 9ai9 这个值替换成 你的php.ini 里session.name的值。
实例访问


一些概念:
 - listeners everything related to incoming connection settings
 - frontend   everything related to incoming connection processing
 - backend   everything related to LB algorithms and server farm
 - session   session processing and flags (very sensible, be careful)
 - server     server connection management, queueing
 - proxy     proxy maintenance (start/stop)
 - CTTPROXY HAProxy 支持全透明代理(已具备硬件防火墙的典型特点): 可以用客户端IP地址或者任何其他地址来连接后端服务器. 
这个特性仅在Linux 2.4/2.6内核打了cttproxy补丁后才可以使用. 
这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。

 - 一个 frontend 要么有filters 或者指向一个 use_filter
 - 一个 backend 要么有 servers 或者指向一个 use_backend
 - 一个proxy总拥有自己的frontend. 另外还有两个参数 :
   - "fi_prm" : 指向拥有filters的proxy(默认是自己)
   - "be_prm" : 指向拥有servers的proxy(默认是自己)
 - 一个request 有一个frontend (fe) 和一个 backend (be). 默认,be指向fe
所有来自client的交互都经过fe,所有来自server的交互都经过be
 - request filters 先调用 ->fe 然后是 ->be. 
因为只有 filters 能修改 ->be,  it is possible to iterate the filters on ->be
    only and stop when ->be does not change anymore.
 - 当(fe != be)时,response filters 先调用 from ->be 然后调用 ->fe 
 - 将解析配置时,会立即配置所有proxies的 ->fi 和 ->be 
 - 当创建session时,proxy的s->fe 和 s->be会被初始化.
Filters通过s->fe->fi_prm 和 s->be->fi_prm被执行;
Servers则通过s->be->be_prm.
 
 
执行结构:
=======================================================================================

server-->(connect to)-->proxy

外部-->proxy-->(loop/hash & build session by cookie)-->server

    <--                                             <--



阅读(4224) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~