技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 系统运维 --> 一些LVS实验配置、工具和方案

一些LVS实验配置、工具和方案

浏览:1056次  出处信息

最近做了一些LVS配置和方案的验证实验,将过程中用到的一些配置、工具和具体的解决方案记录一下。使用DR模式。验证一种不中断业务的RealServer升级或者重启方案。

网络规划:

节点IP地址
ceph1(RealServer1)172.16.0.114
ceph2(RealServer2)172.16.0.115
ceph4(DirectServer)172.16.0.113
客户端:Win 8.1172.16.0.100

一、配置

DirectServer:

vip=172.16.0.113
r1ip=172.16.0.114
r2ip=172.16.0.115
port=$1
if [ -z "$port" ]
then
        port=2100
fi
 
ipvsadm -C
ipvsadm -A -t ${vip}:${port} -s wrr
ipvsadm -a -t ${vip}:${port} -r ${r1ip}:${port} -g
ipvsadm -a -t ${vip}:${port} -r ${r2ip}:${port} -g


RealServer:

#!/bin/sh
VIP=172.16.0.113
BROADCAST=172.16.0.255 #vip's broadcast
 
Usage ()
{
        echo "Usage:`basename $0` (start|stop)"
exit 1
}
 
if [ $# -ne 1 ];then
        Usage
fi
 
case $1 in
start)
        echo "reparing for Real Server"
        echo "1" >;/proc/sys/net/ipv4/conf/lo/arp_ignore
        echo "2" >;/proc/sys/net/ipv4/conf/lo/arp_announce
        echo "1" >;/proc/sys/net/ipv4/conf/all/arp_ignore
        echo "2" >;/proc/sys/net/ipv4/conf/all/arp_announce
        /sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $BROADCAST up
        /sbin/route add -host $VIP dev lo:0
;;
stop)
        /sbin/ifconfig lo:0 down
        echo "0" >;/proc/sys/net/ipv4/conf/lo/arp_ignore
        echo "0" >;/proc/sys/net/ipv4/conf/lo/arp_announce
        echo "0" >;/proc/sys/net/ipv4/conf/all/arp_ignore
        echo "0" >;/proc/sys/net/ipv4/conf/all/arp_announce
        echo "stop Real Server"
;;
*)
        Usage
esac


上述配置是标准的DR模式的配置。

二、工具

RealServer上面提供可以监听固定端口,并接受客户端从TCP连接发送过来的数据的TCP Server服务,将接收到的数据打印到屏幕,并回复当前节点信息给客户端,让客户端能够区分具体的服务是由哪个RealServer提供的。

服务的代码如下:

package com;
 
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
 
publicclass Server
{
 
publicstaticvoid main(String[] args) throws IOException
    {
 
if (args.length < 1)
        {
            System.out.println("arguments error!\nusage: java -jar tcpser.jar server port");
            System.exit(0);
        }
 
int serverport = Integer.parseInt(args[0]);
 
        System.out.println("==============TCP SERVER==============");
 
        ServerSocket server = null;
try
        {
            server = new ServerSocket(serverport);
            System.out.println("Listening Port is " + server.getLocalPort() + "...");
while (true)
            {
                Socket connectedCli = server.accept();
                System.out.println("a new client: " + connectedCli.getInetAddress() + ":" + connectedCli.getPort());
new DataProcesser(connectedCli).start();
            }
        }
catch (Exception e)
        {
            e.printStackTrace();
        }
finally
        {
if (server != null)
            {
                server.close();
            }
        }
    }
}


package com;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
 
publicclass DataProcesser extends Thread
{
private Socket cli;
 
public DataProcesser(Socket clientsocket)
    {
        cli = clientsocket;
    }
 
    @Override
publicvoid run()
    {
        BufferedReader reader = null;
        BufferedWriter writer = null;
try
        {
            reader = new BufferedReader(new InputStreamReader(cli.getInputStream()));
            writer = new BufferedWriter(new OutputStreamWriter(cli.getOutputStream()));
while (true)
            {
                String receivedString = reader.readLine();
if (receivedString != null)
                {
                    System.out.println(cli.getInetAddress() + ":" + cli.getPort() + " " + receivedString);
                    String hostname = InetAddress.getLocalHost().getHostName();
                    writer.write("it's from the host: " + hostname);
                    writer.write("\n");
                    writer.flush();
                }
if ("shutdown".equals(receivedString))
                {
break;
                }
            }
 
        }
catch (Exception e)
        {
            e.printStackTrace();
        }
finally
        {
if (reader != null)
            {
try
                {
                    reader.close();
                }
catch (Exception e2)
                {
                    e2.printStackTrace();
                }
            }
 
if (cli != null)
            {
try
                {
                    cli.close();
                }
catch (Exception e2)
                {
                    e2.printStackTrace();
                }
            }
 
        }
    }
}


将上面的服务端代码导出为jar包:server.jar,部署到两台RealServer上面:

启动信息如下:

root@ceph1:~# java -jar server.jar 2100
==============TCP SERVER==============
Listening Port is 2100...
a new client: /172.16.0.100:49314
a new client: /172.16.0.100:49316


客户端工具:

客户端工具直接使用开源的sockettest工具:http://sourceforge.net/projects/sockettest/

三、验证RealServer的一种安全退出机制

当IPVS正在接受业务时,IPVS将请求按照指定的规则分发给两个节点。当需要重启某一个业务节点时,会存在两个问题:1、正在执行的业务会被中断,如:TCP上面正在做数据交互会中断;2、如何确保不再有新的业务下发到需要重启的节点上面,如果采用LVS服务器将业务节点踢出,那么也会中断已经接入的请求。

其中问题1,一般来说需要服务本身去做判断,判断业务全部完成后,再做下电重启等处理。

对于问题2,需要寻求一种安全的移除业务节点的方案。既不能影响已经接入点业务请求,又不能让新的业务再下发到该节点上面。考虑使用带权重的轮询方式,将某个业务节点的权重设置为0,这样该节点就不会再有业务。但是节点并没有从lvs的配置中删除掉。因此已有的业务不会受影响。

结合客户端工具,和服务端的长连接支持方式,最终很轻松即可验证上述方案,验证步骤:

1、配置好DirectServer,两条分发记录到ceph1和ceph2节点;
2、配置RealServer,启动TCP Server服务;
3、在Windows上面使用sockettest工具分别与LVS的VIP建立长连接;
4、在LVS上面修改配置:

ipvsadm -e -t 172.16.0.113:2100 -r 172.16.0.114:2100 -w 0


5、观察之前已经跟114节点建立的连接是否断开,是否还能继续发送和接受数据。验证结果为:连接不会断开,该连接还能继续处理数据。
6、DirectServer接受到的新的请求,是否还是会转给114节点。验证结果为:0权重生效,所有的业务都只发送到另外一个业务节点上面。
7、到此整个验证结束。

对于RealServer维护期间,需要精细化的维护业务不受损,可以使用如上方案来实现。

建议继续学习:

  1. LVS hash size解决4096个并发的问题    (阅读:5362)
  2. LVS & MySQL NDB Cluster    (阅读:4022)
  3. 记一次LVS/Nginx环境下的访问控制    (阅读:3675)
  4. LVS & MySQL NDB Cluster    (阅读:3661)
  5. 利用MySQL Cluster 7.0 + LVS 搭建高可用环境    (阅读:3229)
  6. 怎么样让 LVS 和 realserver 工作在同一台机器上    (阅读:3124)
  7. 在LVS上实现SNAT网关    (阅读:1152)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1