使用ip route命令实现多链路负载均衡

tinyfisher 发表于 2013-02-07

其实在linux下实现多链路负载均衡很简单,只需借助ip route命令即可。

环境:ubuntu 10.04 ,两个3G网卡,分别为CDMA2000WCDMA

1.分别将两个网卡拨号上网,方法不再具体描述,拨号成功后会多出两条链路ppp0ppp1,注意拨号脚本里不要添加默认网关,(具体请参见《pppd拨号与默认网关》),而是手动添加两条默认路由。

2.利用iptables进行nat转换,不再赘述。

3.此时路由表里会有两条默认路由,其实只有第一个起作用,所有的流量都会从这条链路出去,没有实现负载均衡的效果,只需使用如下命令:

ip route replace default equalize nexthop dev ppp0 weight 1 nexthop dev ppp1 weight 1   

其中weight表示权重,根据链路的实际情况设置相应数值。

4.测试:内网机器进行网络活动,在网关利用命令

tc -s qdisc ls dev ppp0,tc -s qdisc ls dev ppp1  

分别查看两条链路的流量,发现基本流量是按照1:1的比率的。

问题:内网的机器通过多链路网关访问外网速度比单链路得到提升,但是网关本身访问外网的速度比单链路要慢得多,甚至不能访问网站,原因不详,猜想是http数据包从不同的链路进出,不能很好的拼凑给网关。总之现在这个项目不需要网关访问外网,留待以后再讨论。

pppd拨号与默认网关

tinyfisher 发表于 2013-01-29

在linux下使用3G网卡上网,使用pppd工具进行拨号,拨号脚本如下:

nodetach
/dev/ttyUSB0
19200
nocrtscts
connect '/usr/sbin/chat -v -f /etc/ppp/peers/chat_script_unicom'
debug
user "card"
password "card"
ipcp-accept-local
ipcp-accept-remote
defaultroute

其中defaultroute表示拨号成功后,自动添加一条默认路由,如果只使用一个网卡拨号,当然很方便;

但是我发现如果使用两个以上的网卡进行拨号,会产生多条默认路由,这当然也没有问题,只是当其中一条断开后,所有的默认路由都消失了,即使其他的网卡工作正常,也不能上网,所以当有多个网卡拨号的时侯,不建议使用defaultroute这个选项,可以手动添加默认路由:

route add default gw x.x.x.x

DP实例之最长上升子序列LIS

tinyfisher 发表于 2013-01-23
/*
    LIS:最长递增子序列,例如:23453267,最长递增子序列为:234567
    lis(i)表示以a[i]结束的递增子序列的长度
    lis(i)=max{lis(k)+1,1}  k from 0 to i-1
    最长递增子序列长度为max(lis[]);
*/


int LIS(int a[],int len)
{
   int *p=(int *)malloc(sizeof(int)*len);
   int i=0;
   int j=0;
   int result=0;
   if(p==NULL)
        return -1;
   for(i=0;i<len;i++)
   {
       p[i]=1;
       for(j=0;j<i;j++)
       {
           if(a[i]>a[j]&&p[j]+1>p[i])
           {
               p[i]=p[j]+1;
           }
       }
   }
   for(i=0;i<len;i++)
   {
       if(result<p[i])
       {
           result =p[i];
       }
   }
   free(p);
   return result;
}

DP实例之最长公共子序列LCS

tinyfisher 发表于 2012-12-12
/*
    LCS:求最长公共子序列
    例如:s1="abdrge",s2="adreg",则LCS="adre"
    状态方程:lcs(i,j)=lcs(i-1,j-1)+1,其中s1[i]=s2[j]
    或者 lcs(i,j)=max{lcs(i,j-1),lcs(i-1,j)}
*/
int LCS(char *a,char *b)
{
    int len_a=strlen(a);   //行
    int len_b=strlen(b);   //列
    int **len=NULL;
    int **r=NULL;
    int i=0;
    int j=0;
    int lcs_len=0;
    len=(int **)malloc(sizeof(int *)*(len_a+1));       //申请二维数组空间
    r=(int **)malloc(sizeof(int *)*(len_a+1));
    if (len==NULL||r==NULL)
        return -1;
    for(;i<=len_a;i++)
    {
        *(len+i)=(int *)malloc(sizeof(int)*(len_b+1));
        *(r+i)=(int *)malloc(sizeof(int)*(len_b+1));
        if (*(len+i)==NULL||*(r+i)==NULL)
            return -1;
    }

    //LCS状态方程
    for(i=0;i<=len_a;i++)     //初始化
    {
        for(j=0;j<=len_b;j++)
        {
            len[i][j]=0;
            r[i][j]=0;
        }
    }
    for(i=1;i<=len_a;i++)
    {
        for(j=1;j<=len_b;j++)
        {
            if(a[i-1]==b[j-1])
            {
                len[i][j]=len[i-1][j-1]+1;
                r[i][j]=1;
            }
            else if(len[i][j-1]>=len[i-1][j])  //左边的大于等于上边的
            {
                len[i][j]=len[i][j-1];
                r[i][j]=2;
            }
            else
            {
                 len[i][j]=len[i-1][j];
                 r[i][j]=3;
            }
        }
    }

    //打印公共子序列
    print_lcs(r,a,len_a,len_b);
    free(r);
    lcs_len= len[len_a][len_b];
    free(len);
    return lcs_len;
}

void print_lcs(int **r,char *a,int i,int j)
{
    if(i==0||j==0)
        return ;
    else if(r[i][j]==1)
    {
        print_lcs(r,a,i-1,j-1);
        printf("%c",*(a+i-1));
    }
    else if(r[i][j]==2)
        print_lcs(r,a,i,j-1);
    else
        print_lcs(r,a,i-1,j);
}

alt text