负载均衡服务器

每次有客户端连接时选择当前连接数(CR)最小的http服务器进行连接,然后转发请求和应答,用线程实现:

#include	"unp.h"
#include 	<semaphore.h>
#include	<stdlib.h>
#include 	<errno.h>
#include 	<fcntl.h>
#include 	<unistd.h>
#include    	<pthread.h>
#include    	<time.h>
#include	<syslog.h>

#define gettid() syscall(__NR_gettid)
#define         SESSIONNUM   10000

int myreadline(int fd, char *buf, int n);
static void *http(void* connfd);
void init();

struct httpServerInfo
{
    char ip[20];
    char port[10];
    char OS[10];
volatile    int  CR;
    double ACR;
    double cpuUse;
    int    memUse;
} httpServer[4];

struct SessionAdhesions
{
    int ip;
    int choice;
} sessionList[SESSIONNUM];
int sessionIndex;

char  balanceServerIp[20];
char  balanceServerPort[10];
volatile int    CR;
double ACR;
double cpuUse;
int    memUse;

static pthread_mutex_t mutex;

struct eachThreadInfo
{
	int choice;
	int fd;
};

int main(int argc, char **argv)
{
    int			listenfd, connfd;
    pthread_t       	tid;
    socklen_t		clilen;
    struct sockaddr_in  cliaddr, servaddr;
    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family     = AF_INET;
//-------------------初始化结构体----------------------------
    init();
//----------------------------------------------------------
    inet_pton(AF_INET,balanceServerIp,&servaddr.sin_addr);
    servaddr.sin_port=htons(atoi(balanceServerPort));
    Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
    Listen(listenfd, LISTENQ);
    signal(SIGPIPE,SIG_IGN);
    for ( ; ; )
    {
        clilen = sizeof(cliaddr);
        if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0)
        {
            if (errno == EINTR) continue;
            else err_sys("accept error");
        }
       // printf("connected from %s:%u...http\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
	
	struct eachThreadInfo *arg=malloc(sizeof(struct eachThreadInfo));
	arg->fd=connfd;
//-------------------------------------SessionAdhesions---------------------------------------------------------
       /* int j=0;
	int clientIp=cliaddr.sin_addr.s_addr;        
	for(j=0; j<sessionIndex; j++)
        {
            if(clientIp!=sessionList[j].ip)
            {
                arg->choice=sessionList[j].choice;
                break;
            }
        }
        if(j==sessionIndex)
        {
            sessionList[sessionIndex].ip=clientIp;*/
//---------------------------------------balance  connect--------------------------------------------------------
	    int i;
            int eachCR=99999;
            for(i=0; i<4; i++)
            {
                if(httpServer[i].CR<eachCR)
                {
                    arg->choice=i;
                    eachCR=httpServer[i].CR;
                }
            }
	    sessionList[sessionIndex].choice=arg->choice;
            sessionIndex=(sessionIndex+1)%SESSIONNUM;
	    printf("choose httpServer %d!\n\n",arg->choice);
            pthread_create(&tid,NULL,http,(void*)arg);
        }
}


static void *http(void* arg)
{
    pthread_detach(pthread_self());
    struct eachThreadInfo *each=arg;
    pthread_mutex_lock(&mutex);
    httpServer[each->choice].CR++;
    CR++;               
    pthread_mutex_unlock(&mutex);
    int httpd;
    struct sockaddr_in	httpservaddr;
    httpd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&httpservaddr, sizeof(httpservaddr));
    httpservaddr.sin_family = AF_INET;
    httpservaddr.sin_port = htons(atoi(httpServer[each->choice].port));
    Inet_pton(AF_INET, httpServer[each->choice].ip, &httpservaddr.sin_addr);
    connect(httpd, (SA *) &httpservaddr, sizeof(httpservaddr));
    //perror("connect");

    char receiveline[MAXLINE];
    ssize_t n;
    char temp[50];
    while((n=myreadline(each->fd,receiveline,MAXLINE))>2)
    {
        sscanf(receiveline,"%s",temp);
        writen(httpd,receiveline,n);
    }
    writen(httpd,"\r\n",2);

    char 	judge[100];
    unsigned long int	fileLength=0;

    while((n=myreadline(httpd,receiveline,MAXLINE))>2)
    {
        writen(each->fd,receiveline,n);
        sscanf(receiveline,"%s",judge);
        if(!strcmp(judge,"Content-Length:"))
	{
            sscanf(receiveline,"%*s%lu",&fileLength);
	}
    }
    writen(each->fd,"\r\n",2);
   
    while(1)
    {
        if(MAXLINE<fileLength)
        {
            fileLength-=read(httpd, receiveline, MAXLINE);;
            writen(each->fd,receiveline,MAXLINE);
        }
        else
        {
            read(httpd, receiveline, fileLength);
            writen(each->fd,receiveline,fileLength);
            break;
        }
    }
    pthread_mutex_lock(&mutex);
    httpServer[each->choice].CR--;
    CR--;               
    pthread_mutex_unlock(&mutex);
    close(each->fd);
    close(httpd);
    free(arg);
    return NULL;
}

int myreadline(int fd, char *buf, int n)
{
    char ch;
    char *base=buf;
    while(1)
    {
        if(read(fd, &ch, 1)!=1)
        {
            if(errno==EINTR) continue;
            return -1;
        }
        if((*(buf++)=ch)=='\n') break;
    }
    *buf='\0';
    return buf-base;
}

void init()
{
    int conf=open("balance.conf",O_RDONLY);
    char temp[40];
    myreadline(conf,temp,40);
    sscanf(temp,"%*s%s",balanceServerIp);
    myreadline(conf,temp,40);
    sscanf(temp,"%*s%s",balanceServerPort);
    int i=0,j=0;
    int num=4;
    num=num*2;
    for(; i<num; i++)
    {
        myreadline(conf,temp,30);
        if(!(i%2)) sscanf(temp,"%*s%s",httpServer[j].ip);
        else    sscanf(temp,"%*s%s",httpServer[j++].port);
    }
    close(conf);
}

把webbench改为线程版本,用10W连接测试1300k.jpg请求,时间50秒,结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值