ImageVerifierCode 换一换
格式:DOCX , 页数:31 ,大小:26.74KB ,
资源ID:4081264      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4081264.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(软件开发报告.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

软件开发报告.docx

1、软件开发报告负载均衡器软件 开发报告 院系:班级: 成员:1.可行性分析报告1.1 项目背景面对庞大的数据流量,面对集中性的访问,是不是觉得网络服务器岌岌可危呢?不用怕,负载均衡器就能帮你缓解这个问题。负载均衡器通过虚拟IP地址方法,解决了轮流排程所面临的许多问题。使用了负载均衡器集群系统,在外部看来,像是具有一个IP地址的单一服务器一样,当然,这个IP地址是虚拟的,它映射了集群中的每一台机器的地址。所以,在某种程度上,负载均衡器是将整个集群的IP地址报漏给外部网络。当请求到达负载均衡器时,它会重写该请求的头文件,并将之指定到集群中的机器上。如果某台机器被从集群中移除了,请求不会别发往已经不存

2、在的服务器上,因为所有的机器表面上都具有同一个IP地址,即使集群中的某个节点被移除了,该地址也不会发生变化。而且,internet上缓存的DNS条目也不再是问题了。当返回一个应答时,客户端看到的只是从负载均衡器上所返回的结果。也就是说,客户端操作的对象是负载均衡器,对于其更后端的操作,对客户端来讲,是完全透明的。1.2产品分析服务器一致性负载均衡器读取客户端发出的每一个请求中所包含的cookies或url解释。基于所读出的这些信息,负载均衡器就可以重写报头并将请求发往集群中合适的节点上,该节点维护着相应客户端请求的会话信息。在HTTP通信中,负载均衡器可以提供服务器一致性,但并不是通过一个安全

3、的途径(例如:HTTPS)来提供这种服务。当消息被加密后(SSL),负载均衡器就不能读出隐藏在其中的会话信息。通过故障恢复机制获得高可靠性故障恢复发生在当集群中某个节点不能处理请求,需将请求重新导向到其他节点时。主要有两种故障恢复:请求级故障恢复。当集群中的一个节点不能处理请求时(通常是由于down机),请求被发送到其他节点。当然,在导向到其他节点的同时,保存在原节点上的会话信息将会丢失。透明会话故障恢复。当一个引用失败后,负载均衡器会将之发送到集群中其他的节点上,以完成操作,这一点对用户来说是透明的。由于透明会话故障恢复需要节点具备相应的操作信息,因此为了实现该功能,集群中的所有节点必须具有

4、公共存储区域或通用数据库,存储会话信息数据,以提供每个节点在进行单独进程会话故障恢复时所需要的操作信息。既然所有的Web应用请求都必须经过负载均衡系统,那么系统就可以确定活动会话的数量,在任何实例访问中的活动会话的数目,应答的次数,高峰负载次数,以及在高峰期和低谷期的会话的数目,还有其他更多的。所有的这些统计信息都可以被很好的用来调整整个系统的性能。1.3 结论意见 虽然此项目存在一定的技术难度和风险,但我们对项目要达到的目标十分清楚,对所要开发系统将要实现的功能也非常了解。而且有一些成品作为参考,并且在项目的实施过程中我们能够获得帮助,我认为只要我们能够认真思考、仔细规划、明确分工,我们可以

5、承担此项目的开发。2.项目开发计划2.1 总体功能要求1.扩展网络设备和服务器的带宽2.增加吞吐量3.加强网络数据处理能力4.提高网络的灵活性和可用性2.2 软件开发平台要求Visual c+ 6.0SQL Server 2008C+ Builder网络架构:完全支持TCP/IP协议2.3 软件项目的开发实施过程管理要求3.软件开发3.1 软件的需求分析1DNS负载均衡最早的负载均衡技术是通过DNS来实现的,在DNS中为多个地址配置同一个名字,因而查询这个名字的客户机将得到其中一个地址,从而使得不同的客户访问不同的服务器,达到负载均衡的目的。DNS负载均衡是一种简单而有效的方法,但是它不能区分

6、服务器的差异,也不能反映服务器的当前运行状态。2代理服务器负载均衡使用代理服务器,可以将请求转发给内部的服务器,使用这种加速模式显然可以提升静态网页的访问速度。然而,也可以考虑这样一种技术,使用代理服务器将请求均匀转发给多台服务器,从而达到负载均衡的目的。3地址转换网关负载均衡支持负载均衡的地址转换网关,可以将一个外部IP地址映射为多个内部IP地址,对每次TCP连接请求动态使用其中一个内部地址,达到负载均衡的目的。4协议内部支持负载均衡除了这三种负载均衡方式之外,有的协议内部支持与负载均衡相关的功能,例如HTTP协议中的重定向能力等,HTTP运行于TCP连接的最高层。5NAT负载均衡NAT简单

7、地说就是将一个IP地址转换为另一个IP地址,一般用于未经注册的内部地址与合法的、已获注册的InternetIP地址间进行转换。适用于解决InternetIP地址紧张、不想让网络外部知道内部网络结构等的场合下。6反向代理负载均衡普通代理方式是代理内部网络用户访问internet上服务器的连接请求,客户端必须指定代理服务器,并将本来要直接发送到internet上服务器的连接请求发送给代理服务器处理。反向代理(ReverseProxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理

8、服务器对外就表现为一个服务器。反向代理负载均衡技术是把将来自internet上的连接请求以反向代理的方式动态地转发给内部网络上的多台服务器进行处理,从而达到负载均衡的目的。7混合型负载均衡在有些大型网络,由于多个服务器群内硬件设备、各自的规模、提供的服务等的差异,可以考虑给每个服务器群采用最合适的负载均衡方式,然后又在这多个服务器群间再一次负载均衡或群集起来以一个整体向外界提供服务(即把这多个服务器群当做一个新的服务器群),从而达到最佳的性能。将这种方式称之为混合型负载均衡。此种方式有时也用于单台均衡设备的性能不能满足大量连接请求的情况下。3.2软件的概要设计软件负载均衡解决方案是指在一台或多

9、台服务器相应的操作系统上安装一个或多个附加软件来实现负载均衡,DNSLoadBalanceCheckPointFirewall-1ConnectControl等,它的优点是基于特定环境,配置简单,使用灵活,成本低廉,可以满足一般的负载均衡需求。硬件负载均衡解决方案是直接在服务器和外部网络间安装负载均衡设备,这种设备通常称之为负载均衡器,由于专门的设备完成专门的任务,独立于操作系统,整体性能得到大量提高,加上多样化的负载均衡策略,智能化的流量管理,可达到最佳的负载均衡需求。一般而言,硬件负载均衡在功能、性能上优于软件方式,不过成本昂贵。本地负载均衡能有效地解决数据流量过大、网络负荷过重的问题,并

10、且不需花费昂贵开支购置性能卓越的服务器,充分利用现有设备,避免服务器单点故障造成数据流量的损失。其有灵活多样的均衡策略把数据流量合理地分配给服务器群内的服务器共同负担。即使是再给现有服务器扩充升级,也只是简单地增加一个新的服务器到服务群中,而不需改变现有网络结构、停止现有的服务。全局负载均衡主要用于在一个多区域拥有自己服务器的站点,为了使全球用户只以一个IP地址或域名就能访问到离自己最近的服务器,从而获得最快的访问速度,也可用于子公司分散站点分布广的大公司通过企业内部互联网来达到资源统一合理分配的目的。3.3软件的详细设计1.轮转法:轮转算法是所有调度算法中最简单也最容易实现的一种方法。在一个

11、任务队列里,队列的每个成员(节点)都具有相同的地位,轮转法简单的在这组成员中顺序轮转选择。在负载平衡环境中,均衡器将新的请求轮流发给节点队列中的下一节点,如此连续、周而复始,每个集群的节点都在相等的地位下被轮流选择。这个算法在DNS域名轮询中被广泛使用。 轮转法的活动是可预知的,每个节点被选择的机会是1/N,因此很容易计算出节点的负载分布。轮转法典型的适用于集群中所有节点的处理能力和性能均相同的情况,在实际应用中,一般将它与其他简单方法联合使用时比较有效。2.散列法:散列法也叫哈希法(HASH),通过单射不可逆的HASH函数,按照某种规则将网络请求发往集群节点。哈希法在其他几类平衡算法不是很有

12、效时会显示出特别的威力。例如,在前面提到的UDP会话的情况下,由于轮转法和其他几类基于连接信息的算法,无法识别出会话的起止标记,会引起应用混乱。 而采取基于数据包源地址的哈希映射可以在一定程度上解决这个问题:将具有相同源地址的数据包发给同一服务器节点,这使得基于高层会话的事务可以以适当的方式运行。相对称的是,基于目的地址的哈希调度算法可以用在Web Cache集群中,指向同一个目标站点的访问请求都被负载平衡器发送到同一个Cache服务节点上,以避免页面缺失而带来的更新Cache问题。3.最少连接法:在最少连接法中,平衡器纪录目前所有活跃连接,把下一个新的请求发给当前含有最少连接数的节点。这种算

13、法针对TCP连接进行,但由于不同应用对系统资源的消耗可能差异很大,而连接数无法反映出真实的应用负载,因此在使用重型Web服务器作为集群节点服务时(例如Apache服务器),该算法在平衡负载的效果上要打个折扣。为了减少这个不利的影响,可以对每个节点设置最大的连接数上限(通过阈值设定体现)。4.最低缺失法:在最低缺失法中,平衡器长期纪录到各节点的请求情况,把下个请求发给历史上处理请求最少的节点。与最少连接法不同的是,最低缺失记录过去的连接数而不是当前的连接数。5.最快响应法:平衡器记录自身到每一个集群节点的网络响应时间,并将下一个到达的连接请求分配给响应时间最短的节点,这种方法要求使用ICMP包或

14、基于UDP包的专用技术来主动探测各节点。 在大多数基于LAN的集群中,最快响应算法工作的并不是很好,因为LAN中的ICMP包基本上都在10ms内完成回应,体现不出节点之间的差异;如果在 WAN上进行平衡的话,响应时间对于用户就近选择服务器而言还是具有现实意义的;而且集群的拓扑越分散这种方法越能体现出效果来。这种方法是高级平衡基于拓扑结构重定向用到的主要方法。6.加权法:加权方法只能与其他方法合用,是它们的一个很好的补充。加权算法根据节点的优先级或当前的负载状况(即权值)来构成负载平衡的多优先级队列,队列中的每个等待处理的连接都具有相同处理等级,这样在同一个队列里可以按照前面的轮转法或者最少连接

15、法进行均衡,而队列之间按照优先级的先后顺序进行均衡处理。在这里权值是基于各节点能力的一个估计值。3.4 软件的编码#include #include #include #include conn.h#include log.h#include fdwrapper.hconn:conn() m_srvfd = -1; m_clt_buf = new char BUF_SIZE ; if( !m_clt_buf ) throw std:exception(); m_srv_buf = new char BUF_SIZE ; if( !m_srv_buf ) throw std:exception(

16、); reset();conn:conn() delete m_clt_buf; delete m_srv_buf;void conn:init_clt( int sockfd, const sockaddr_in& client_addr ) m_cltfd = sockfd; m_clt_address = client_addr;void conn:init_srv( int sockfd, const sockaddr_in& server_addr ) m_srvfd = sockfd; m_srv_address = server_addr;void conn:reset() m_

17、clt_read_idx = 0; m_clt_write_idx = 0; m_srv_read_idx = 0; m_srv_write_idx = 0; m_srv_closed = false; m_cltfd = -1; memset( m_clt_buf, 0, BUF_SIZE ); memset( m_srv_buf, 0, BUF_SIZE );RET_CODE conn:read_clt() int bytes_read = 0; while( true ) if( m_clt_read_idx = BUF_SIZE ) log( LOG_ERR, _FILE_, _LIN

18、E_, %s, the client read buffer is full, let server write ); return BUFFER_FULL; bytes_read = recv( m_cltfd, m_clt_buf + m_clt_read_idx, BUF_SIZE - m_clt_read_idx, 0 ); if ( bytes_read = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) break; return IOERR; else if ( bytes_read = 0 ) return CLOSED; m_c

19、lt_read_idx += bytes_read; return ( ( m_clt_read_idx - m_clt_write_idx ) 0 ) ? OK : NOTHING;RET_CODE conn:read_srv() int bytes_read = 0; while( true ) if( m_srv_read_idx = BUF_SIZE ) log( LOG_ERR, _FILE_, _LINE_, %s, the server read buffer is full, let client write ); return BUFFER_FULL; bytes_read

20、= recv( m_srvfd, m_srv_buf + m_srv_read_idx, BUF_SIZE - m_srv_read_idx, 0 ); if ( bytes_read = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) break; return IOERR; else if ( bytes_read = 0 ) log( LOG_ERR, _FILE_, _LINE_, %s, the server should not close the persist connection ); return CLOSED; m_srv_

21、read_idx += bytes_read; return ( ( m_srv_read_idx - m_srv_write_idx ) 0 ) ? OK : NOTHING;RET_CODE conn:write_srv() int bytes_write = 0; while( true ) if( m_clt_read_idx = m_clt_write_idx ) m_clt_read_idx = 0; m_clt_write_idx = 0; return BUFFER_EMPTY; bytes_write = send( m_srvfd, m_clt_buf + m_clt_wr

22、ite_idx, m_clt_read_idx - m_clt_write_idx, 0 ); if ( bytes_write = -1 ) if( errno = EAGAIN | errno = EWOULDBLOCK ) return TRY_AGAIN; log( LOG_ERR, _FILE_, _LINE_, write server socket failed, %s, strerror( errno ) ); return IOERR; else if ( bytes_write = 0 ) return CLOSED; m_clt_write_idx += bytes_wr

23、ite; RET_CODE conn:write_clt() int bytes_write = 0; while( true ) if( m_srv_read_idx = m_srv_write_idx ) m_srv_read_idx = 0; m_srv_write_idx = 0; return BUFFER_EMPTY; bytes_write = send( m_cltfd, m_srv_buf + m_srv_write_idx, m_srv_read_idx - m_srv_write_idx, 0 ); if ( bytes_write = -1 ) if( errno =

24、EAGAIN | errno = EWOULDBLOCK ) return TRY_AGAIN; log( LOG_ERR, _FILE_, _LINE_, write client socket failed, %s, strerror( errno ) ); return IOERR; else if ( bytes_write = 0 ) return CLOSED; m_srv_write_idx += bytes_write; #ifndef FDWRAPPER_H#define FDWRAPPER_H#include #include #include int setnonbloc

25、king( int fd ) int old_option = fcntl( fd, F_GETFL ); int new_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option;void add_read_fd( int epollfd, int fd ) epoll_event event; event.data.fd = fd; event.events = EPOLLIN | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_ADD, fd,

26、&event ); setnonblocking( fd );void add_write_fd( int epollfd, int fd ) epoll_event event; event.data.fd = fd; event.events = EPOLLOUT | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd );void closefd( int epollfd, int fd ) epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 ); clos

27、e( fd );void removefd( int epollfd, int fd ) epoll_ctl( epollfd, EPOLL_CTL_DEL, fd, 0 );void modfd( int epollfd, int fd, int ev ) epoll_event event; event.data.fd = fd; event.events = ev | EPOLLET; epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );#endif#include #include #include #include log.hstatic

28、int level = LOG_INFO;static int LOG_BUFFER_SIZE = 2048;static const char* loglevels = emerge!, alert!, critical!, error!, warn!, notice:, info:, debug:;void set_loglevel( int log_level ) level = log_level;void log( int log_level, const char* file_name, int line_num, const char* format, . ) if ( log_

29、level level ) return; time_t tmp = time( NULL ); struct tm* cur_time = localtime( &tmp ); if ( ! cur_time ) return; char arg_buffer LOG_BUFFER_SIZE ; memset( arg_buffer, 0, LOG_BUFFER_SIZE ); strftime( arg_buffer, LOG_BUFFER_SIZE - 1, %x %X , cur_time ); printf( %s, arg_buffer ); printf( %s:%04d , file_name, line_num ); printf( %s , loglevels log_level - LOG_EMERG ); va_list arg_list; va_start( arg_list, format ); memset( arg_buffer, 0, LOG_BUFFER_SIZE ); vsnprintf( arg_buffer, LOG_BUFFER_SIZE - 1, format, arg_list ); printf( %sn, arg_buffer ); fflush( stdout ); va_end( arg_list );#include

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1