7.5 算法及流程
(1) ip_portfw_del
格式: static __inline __ int ip_portfw_del(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr)
返回值:如果模块的访问计数〉0,则返回一个大于0的值,否则返回0;
处理流程:
1. 在双向链表中找到这样的ip_portfw *n 结构,满足:
(n->lport == lport && (!laddr || n->laddr == laddr) && (!raddr || n->raddr == raddr) && (!rport || n->rport == rport )),从链表中删除此入口,释放n结构。
1. 若(&mmod_self -> mmod_nent)为真,则返回ESRCH,否则返回0。
(2) ip_portfw_flush
格式: static __inline__ void ip_portfw_flush(void)
返回值:无。
处理流程:
1. 对于TCP 和UDP链,循环做2. 3步
2. 从链表上删除一个入口,释放结构n。
3. 取下一入口。
(3) ip_portfw_lookup
格式: static __inline__ struct ip_portfw *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr, __u32 *daddr_p, __u16 *dport_p)
返回值:返回一个ip_portfw结构的变量n。
处理流程:
1.在双向链表中找到这样的ip_portfw *n 结构,满足:
(lport == n->lport && laddr == n->laddr) ,若没有找到,则n = NULL。
2.赋值:*daddr_p = n->raddr;*dport_p = n->rport。
3.返回n。
(4) ip_portfw_edit
格式: static __inline__ int ip_portfw_edit(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, int pref)
返回值:返回满足匹配条件的表项的数目。
处理流程:
1. 设count为0。
2. 在双向链表中找这样的n,满足:( lport == n->lport && (!laddr || laddr == n->laddr) && (!raddr || raddr == n->raddr) && (!rport || rport == n->rport )) 。
3. 为n设置权重。
4. 设n->pref_cnt = pref。
5. 每找到一个匹配项, count都加1。
6. 解读锁portfw_lock。
7. 返回count。
(5) ip_portfw_add
格式: static __inline__ int ip_portfw_add(__u16 protocol, __u16 lport,__u32 laddr, __u16 rport,__u32 raddr, int pref)
返回值:成功:返回0;失败:返回EINVAL。
处理流程:
1. 调用ip_portfw_edit, 若有匹配项,则返回0。
2. 为npf分配一个 struct ip_portfw的空间,若分配失败,则返回"无可用空间" 。
3. MOD_INC_USE_COUNT。
4. npf清0。
5. npf->laddr = laddr;
npf->lport = lport;
npf->rport = rport;
npf->raddr = raddr;
npf->pref = pref;
设npf的访问计数为npf的权重;
6. 调用INIT_LIST_HEAD初始化npf->list。
7. 加写锁&portfw_lock。
8. 调用list_add增加一项到链头。
9. 解写锁。
10. 增加mmod_self计数。
11. 返回0。
(6) portfw_ctl
格式: static __inline__ int portfw_ctl(int optname,struct ip_masq_ctl *mctl, int optlen) 返回值:成功:返回0;失败:返回EINVAL。
处理流程:
1. 如果cmd为IP_MASQ_CMD_NONE,返回0。
2. 如果cmd为IP_MASQ_CMD_ADD,调用 ip_portfw_add。
3. 如果cmd为IP_MASQ_CMD_DEL,调用 ip_portfw_del。
4. 如果cmd为IP_MASQ_CMD_FLUSH,调用ip_portfw_flush。
5. 返回EINVAL。
(7)portfw_in_creat
格式: static struct ip_masq *portfw_in_creat(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
返回值: 成功:返回ms。
处理流程:
1. 加写锁&portfw_lock。
2. 调用ip_portfw_lookup,若找到匹配项,则调ip_masq_new创建一个新入口表项ms。
3. 调用ip_masq_listen。
4. pf的访问计数减一,若访问计数为0,则设pf的访问计数为pf的权重,将pf 从双向链表中删除,并重新加到链表尾。
5. 返回ms。
(8) 函数getip()
格式:asmlinkage getip(__u32 laddr, __u16 lport, __u32 raddr, __u16 rport) 返回值:无。
处理流程:
1.调用ip_portfw_flush清空ip端口转发链表。
2.调用ip_portfw_add(laddr, lport, raddr, rport, 1)向链表中加入新表项。
8.调度模块的分析
8.1 设计思想
调度模块的主要任务是:
1. 平衡器向各台实际服务器发送收集负载信息的命令。
2. 各台实际服务器分别运行取cpu运行队列长度的程序。
3. 各台机器将各自的cpu运行队列长度信息回传给平衡器。
4.平衡器对各台机器的cpu运行队列长度进行比较并选出cpu运行队列长度最短的机器,认为此机器就是负载最轻的机器。
5. 通过系统调用将负载最轻的机器的IP地址传入ip端口转发模块。
8.2 模块流程


8.3 结构设计
程序名 | 功能 | 源程序 |
client程序 | 收集server方的负载信息并进行处理 | client.c |
server程序 | 收集本机负载信息并传向client方 | server.c |
负载信息收集程序 | 取cpu运行队列长度 | cpu.c |
8.4 主要数据结构
struct info{ char host[15]; char cpu[20]; } |
8.5 算法及流程
(1) cpu.c
处理流程:
1. 调用readprottab2取得进程表p_table。
2. 调用do_stat计算 cpu运行队列长度的信息。
(2) 函数do_stat
格式:void do_stat(proc_t **p, float elapsed_time, int pass, int ctl)
处理流程:
1. 设进程状态变量sleeping =0,stopped = 0, zombie = 0, running = 0。
2. 做以下循环:3,4步。
3. 根据进程表取得一个进程,判断它的状态是sleeping、 stopped 、 zombie还是 running,并且给相应的变量sleeping、 stopped 、 zombie、 running加1。
4. 取下一个进程,返回3。
5. 打印正在运行的进程的个数。
(3)client.c
处理流程:
1. 循环做以下步骤:2-11。
2. 设置控制变量i,循环做3-10步。
3. 如果i < NUM(内部网中机器的总数),做以下步骤。
4. 创建套接口sockfd。
5. 调用connect请求建立一个连接。
6. 调用recv将取得的字节流放入缓冲区buf中。
7. 将buf转换为struct info的格式并将转换后的结果赋给load[I]。
8. 比较各机器的cpu运行队列的长度并且确定负载最轻的机器的IP值,以该值为参数通过自定义的系统调用getip进入内核。
9. 关闭套接口sockfd。
8. 睡眠30秒钟。
(4)server.c
流程:
1. 创建套接口sockfd用来侦听。
2. 调用bind进行绑定。
3. 调用listen进行侦听。
4. 循环做以下步骤:5-11。
5. 调用accept接受连接请求。
6. 调用gethostname取得主机名,调用gethostbyname取得主机IP。
7. 将主机IP赋给load->host。
8. 将/loadbalan/cpu.o的运行结果写入./cpuinfo。
9. 打开./cpuinfo文件,将读取到的值写入 load->cpu。
10. 将结构load以字节流的形式发送出去。
11. 关闭套接口。
9. 系统功能及特点
该负载平衡系统具有以下功能:
(1) 能够对基于TCP/IP协议的多种服务如telnet、ftp、 http等进行转发。在应用程序中,用户可以通过加入特定服务对应的端口号(如ftp对应的端口号是21)来增加对特定的服务的支持。
(2)实现了动态负载平衡。负载平衡器不断收集各台实际服务器正在运行的进程的个数,通过比较找出具有最少运行进程个数的机器,并且将请求发向这台机器。这种负载平衡是随各台机器现有的负载情况的变化而变化的,因此是动态的负载平衡。
(3)保证了持续连接。当来一个新的请求时,负载平衡器查找已建立连接的表项来看是否有匹配表项,如果发现已有匹配项,则将请求发往对应的实际服务器,这样就保证了来自同一个用户的同一个服务的多次请求能发送到同一台实际服务器上。
该负载平衡器具有以下的性能特点:
(1)具有较短的响应时间。从负载平衡器向集群中实际服务器发出收集负载的请求到决定出负载最轻的机器所用的总时间约为30ms,该负载平衡系统能够保证毫秒级的响应时间。
(2)具有良好的可伸缩性。用户可以在应用程序中对集群中的机器个数进行控制,程序中有一个数组来记录机器的IP地址,因此增加一台机器只需要向数组中增加一个新的元素,删除一台机器只需要从数组中删除对应的元素。
(3)具有良好的容错性。当集群中的某台机器突然崩溃时,应用程序能够立即发现,并且不会再将请求分发给失效的机器;当机器修复了错误重新进入集群中时,应用程序能够探测到并开始进行正常的负载收集工作。
.分页: [1] [2] [3]
TAG: Linux 集群 理论