负载均衡服务器

每次有客户端连接时选择当前连接数(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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值