用python socket实现LVS自动权衡调整及监控管理

和朋友一起搞定了这个应用~  以前是用shell写的,方法比较二,而且性能不好,因为公司有更好的解决方案,所以这个方法也就可以分享出来了>

一个用python来监控 lvs的调度情况,根据后端服务器负载的情况,来实现lvs权衡负载

因为每个人的环境不一样,最好是看下代码,多方面测试再用~

这个程序需设置一个阈值,在lvs端运行server.py 在realserver运行client.py 。

后端的服务器会把当前的负载情况,利用socket的方式发送给 LVS端, 随之LVS端会检查 ipvsadm -L -n 的情况。

如果检查达到警告阈值,会相应的平衡,如果不是,什么都没发生。当负载回到正常,权重设置回到原来的值。

我会在三更半夜的时候,把代码讲解注释的~  

通信用xmlrpc,不适合大型的应用,对付这个简单报告的话,还是可以的。

给个小例子大家可以看看~

xml rpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据。一个rpc系统,必然包括2个部分:1.rpc client,用来向rpc server调用方法,并接收方法的返回数据;2.rpc server,用于响应rpc client的请求,执行方法,并回送方法执行结果。

rpcserver

import SimpleXMLRPCServer     

class HelloWorld:
    def say(self):
        return "hello, world!" 

obj = HelloWorld()
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 80))
server.register_instance(obj)
print "Listening on port 80..."
server.serve_forever()

rpcclient

import xmlrpclib
server = xmlrpclib.ServerProxy("http://localhost:80")
print "result: " + server.say()

server.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-   

# 绑定自己的ip 和 一个可用的端口
serverIP = '172.17.0.100'
serverPort = 12219
# 设置服务器的负载阀值
LoadAvg_crit_threshold = '1.00'
LoadAvg_warn_threshold = '0.60'
# 什么时候,会设置权衡 比如设置5的话 就是20%
changeWeightWarn = 4    # 100%/4 = -25% of original
changeWeightCrit = 2    # 100%/2 = -50% of original    

from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import string,socket    

# convert hex2dec
def hex2dec(s):
    return int(s, 16)    

# simple routine to read from a file, line by line
def readLines(filename):
    f = open(filename, "r")
    lines = f.readlines()
    return lines    

# 或者 realserver ip 在 /proc/net/ip_vs 的连接情况
# This ACL should be built with the following format:
# { RIP = [VIP, WEIGHT, WEIGHTCURRENT, VPORT, RPORT] }
print "Building ACL from LVS table ..."
accessList={}
for line in readLines('/proc/net/ip_vs'):
    if line.split()[0] == 'TCP' or line.split()[0] == 'UDP':
        vIP = line.split()[1].split(':')[0]
        vIPvIPfst = vIP[0:2]
        vIPvIPscd = vIP[2:4]
        vIPvIPtrd = vIP[4:6]
        vIPvIPfth = vIP[6:8]
        vIPport = hex2dec(line.split()[1].split(':')[1])
        virtualIP = str(hex2dec(vIPfst)) + "." + str(hex2dec(vIPscd)) + "." + str(hex2dec(vIPtrd)) + "." + str(hex2dec(vIPfth))
    if line.split()[0] == '->':
        if len(str(line.split()[1])) == 13:
            rsIP = line.split()[1].split(':')[0]
            rsIPrsIPfst = rsIP[0:2] # first octet
            rsIPrsIPscd = rsIP[2:4] # second octet
            rsIPrsIPtrd = rsIP[4:6] # third octet
            rsIPrsIPfth = rsIP[6:8] # fourth octet
            rsIPport = hex2dec(line.split()[1].split(':')[1])
            # get routing type (nat/direct/tun)
            rsRouteType = line.split()[2]
            if rsRouteType == "Route":
                rsRoute = "g"
            elif rsRouteType == "Masq":
                rsRoute = "m"
            elif rsRouteType == "Tunnel":
                rsRoute = "i"
            # compile RIP
            realserverIP = str(hex2dec(rsIPfst)) + "." + str(hex2dec(rsIPscd)) + "." + str(hex2dec(rsIPtrd)) + "." + str(hex2dec(rsIPfth))
            # build realserver list
            realserverList = [virtualIP]
            # add original weight to list
            realserverList.append(line.split()[3])
            # add current weight to list (same as original weight)
            realserverList.append(line.split()[3])
            # add virtual port to list
            realserverList.append(vIPport)
            # add real port to list
            realserverList.append(rsIPport)
            # add routing type to list
            realserverList.append(rsRoute)
            # add keypair (ip:weight)  to ACL
            accessList[realserverIP] = realserverList
            print "Adding %s:%s:%s:%s:%s:%s to ACL as RIP:VIP:weightOrig:weightCurrent:vPort:rPort:rType" % (str(realserverIP),str(virtualIP),str(accessList[realserverIP][1]),str(vIPport),str(rsIPport),str(rsRouteType))    

# 或者负载情况 并且 pushLoad
def pushLoad_function(LoadAvg, clientIP):
    import os
    LoadAvgLoadAvg1 = LoadAvg.split()[0]
    #print "DEBUG: Client reports IP:  %s " % clientIP
    # Determine original weight
    rsWeightOriginal = accessList[clientIP][1]
    #print "DEBUG: Original weight of rs: %s " % rsWeightOriginal
    # Determine changed weight
    rsWeightCurrent = accessList[clientIP][2]
    #print "DEBUG: Current weight of rs: %s " % rsWeightCurrent
    # Determine if CRITICAL threshold is reached
    if float(LoadAvg1) >= float(LoadAvg_crit_threshold):
        print "CRITICAL: Load Average (1min) threshold (%s) reached: %s" % (str(LoadAvg_crit_threshold),LoadAvg1)
        rsWeightHalf = int(rsWeightOriginal) - int(rsWeightOriginal)/2
        # Only change weight if not already changed
        if not int(rsWeightCurrent) == int(rsWeightHalf):
            print "Changing realserver's weight to 50% of original"
            print "Running /sbin/ipvsadm -e -t " + str(accessList[clientIP][0]) + ":" + str(accessList[clientIP][3]) + " -r " + str(clientIP) + ":" + str(accessList[clientIP][4]) + " -w " + str(rsWeightHalf) + " -" + str(accessList[clientIP][5])
            cmd = "/sbin/ipvsadm -e -t " + str(accessList[clientIP][0]) + ":" + str(accessList[clientIP][3]) + " -r " + str(clientIP) + ":" + str(accessList[clientIP][4]) + " -w " + str(rsWeightHalf) + " -" + str(accessList[clientIP][5])
            os.system(cmd)
            # Setting new weight in list
            accessList[clientIP][2] = rsWeightHalf
        else:
            print "Weight already changed. Doing nothing."
    # Determine if WARNING threshold is reached
    elif float(LoadAvg1) >= float(LoadAvg_warn_threshold):
        print "WARNING: Load Average (1min) threshold (%s) reached: %s" % (str(LoadAvg_warn_threshold),LoadAvg1)
    rsWeightQuart = int(rsWeightOriginal) - int(rsWeightOriginal)/4
    # Only change weight if not already changed
        if not int(rsWeightCurrent) == int(rsWeightQuart):
            print "Changing realserver's weight to 75% of original"
            print "Running /sbin/ipvsadm -e -t " + str(accessList[clientIP][0]) + ":" + str(accessList[clientIP][3]) + " -r " + str(clientIP) + ":" + str(accessList[clientIP][4]) + " -w " + str(rsWeightQuart) + " -" + str(accessList[clientIP][5])
            cmd = "/sbin/ipvsadm -e -t " + str(accessList[clientIP][0]) + ":" + str(accessList[clientIP][3]) + " -r " + str(clientIP) + ":" + str(accessList[clientIP][4]) + " -w " + str(rsWeightQuart) + " -" + str(accessList[clientIP][5])
        os.system(cmd)
            # Setting new weight in list
            accessList[clientIP][2] = rsWeightQuart
        else:
            print "Weight already changed. Doing nothing."

    else:
        print "OK: Load Average (1min) threshold normal: %s" % LoadAvg1
    # Setting weight back to original value if not already set
    if not int(rsWeightCurrent) == int(rsWeightOriginal):
        print "Setting weight back to original value of %s" % str(rsWeightOriginal)
        print "Running /sbin/ipvsadm -e -t " + str(accessList[clientIP][0]) + ":" + str(accessList[clientIP][3]) + " -r " + str(clientIP) + ":" + str(accessList[clientIP][4]) + " -w " + str(rsWeightOriginal)
        cmd = "/sbin/ipvsadm -e -t " + str(accessList[clientIP][0]) + ":" + str(accessList[clientIP][3]) + " -r " + str(clientIP) + ":" + str(accessList[clientIP][4]) + " -w " + str(rsWeightOriginal)
        os.system(cmd)
        accessList[clientIP][2] = rsWeightOriginal
    return LoadAvg1    

# subclass SimpleXMLRPCServer to grab client_address
class Server(SimpleXMLRPCServer):
    def __init__(self,*args):
        SimpleXMLRPCServer.__init__(self,(args[0],args[1]))
    def server_bind(self):
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        SimpleXMLRPCServer.server_bind(self)
    def verify_request(self,request, client_address):
        print "\n"
    clientIP = client_address[0]
    if accessList.has_key(clientIP):
            print "Client (%s) in LVS table." % clientIP
            return 1
    else:
        print "Client (%s) NOT in LVS table." % clientIP
    return 0

if __name__ == "__main__":
    print "Starting up ..."
    server = Server(serverIP,serverPort)
    server.register_function(pushLoad_function, 'pushLoad')
    server.logRequests = 0
    server.serve_forever()

client.py

#!/usr/bin/env python    

import xmlrpclib
import socket    

# IP:port settings of director
directorIP = '172.17.0.100'
directorPort = '12219'

# Connect to server
s = xmlrpclib.ServerProxy("http://" + directorIP + ":" + directorPort)    

# FIXME: Implement timeout (else RPC request will hang indefinately)
#socket.setdefaulttimeout(60)    

def readLine(filename):
    f = open(filename, "r")
    lines = f.readline()
    return lines    

LoadAvg = readLine('/proc/loadavg')    

# Fugly way to grab our ip. A better way would be to take our initial
# connect and get it from there. I don't know how (yet).
from socket import socket, SOCK_DGRAM, AF_INET
ugly = socket(AF_INET, SOCK_DGRAM)
ugly.connect((directorIP, int(directorPort)))
myIP = ugly.getsockname()[0]    

myLoad = s.pushLoad(LoadAvg,myIP)    

print "DEBUG: pushed current 1m load avg of " + str(myLoad)

本文出自 “峰云,就她了。” 博客,请务必保留此出处http://rfyiamcool.blog.51cto.com/1030776/1141785

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索server
, split
, str
, print
, weight
floating ip
lvs socket 负载均衡、lvs socket、lvs socket配置、lvs websocket、java socket lvs,以便于您获取更多的相关知识。

时间: 2024-12-09 09:18:00

用python socket实现LVS自动权衡调整及监控管理的相关文章

python socket 数据发送前后不一致,会自动增加一个空格。

问题描述 python socket 数据发送前后不一致,会自动增加一个空格. 我用py写了个server,用py的自带库tk写了个client,运行正常. 后面我又用QT4库写了个client,问题出来了: 我在client上有一个单行输入框,点击send按扭后,会获取单行输入框的text,并把这个内容发送给服务端,此时服务端接收消息,把这个消息再返回客户端. 问题出来了,如果我单行输入框中的内容是abc,也就是长度为3的字符串,服务器接收后却是a b c ,也就是在每个字符后面都自动加了一个

Python socket编程实例详解

  本文实例形式较为详细的讲述了Python socket编程.分享给大家供大家参考.具体如下: 复制代码 代码如下: sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 上面的代码创建了一个socket对象.type参数代表套接字类型,可为SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字).AF_INET表示创建的是ip v4的类型. 复制代码 代码如下: socket(address_family,type,pro

Python Socket通讯程序例子

python中内置的socket模块使得网络编程更加简单化,下面就通过两个小小脚本来了解客户端如何与服务器端建立socket. 客户端代码: #clietn.py if __name__ == '__main__':  #判断是否调用自己本身,如果不是则__name__为脚本名称 import socket  #导入我们所需的socket模块sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #第一步是创建socket对象.调用so

python学习-Python socket 聊天器

问题描述 Python socket 聊天器 用python做一个多用户的聊天器.就是指一个服务器,然后不同的电脑上开启客户端,都能连接,还可以互相传递消息.但是现在的问题是都能连接上,但相互之间不能通信.一个连接上后就把原来连接的挤掉了.该怎么解决? 解决方案 你没写端口吧,明显通讯拥挤 解决方案二: 客户端都是连接到服务器,那么数据应该是通过服务器来中转 解决方案三: python socket聊天小工具

Python Socket 网络编程

原文:Python Socket 网络编程 Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ 聊天.收发 email 等等.要解决网络上两台主机之间的进程通信问题,首先要唯一标识该进程,在 TCP/IP 网络协议中,就是通过 (IP地址,协议,端口号) 三元组来标识进程的,解决了进程标识问题,就有了通信的基础了. 本文主要介绍使用 Python 进

Python Socket 编程——聊天室示例程序

原文:Python Socket 编程--聊天室示例程序 上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的理解. 聊天室程序需求 我们要实现的是简单的聊天室的例子,就是允许多个人同时一起聊天,每个人发送的消息所有人都能接收到,类似于 QQ 群的功能,而不是点对点的 QQ 好友之间的聊天.如下图: 图来自:http://www.ibm.com/de

有关python socket 多线程问题

问题描述 有关python socket 多线程问题 我现在写的程序是模拟p2p DHT 就是peer1 知道peer2 和 peer3的port 依此类推 现在我写了一个程序 打开的每个xterm端口是一个peer 窗口里可以显示ping所返回的信息代码如下我测试了好久 有的显示返回信息 有的显示接收信息 有的豆显示 有的根本不显示刚学编程半年 python很多东西不了解 socket 和多线程完全是先学先用的 所以请各位看一下到底问题出在哪里 以下是代码 import sysimport t

server-java socket客户端和Python socket客户端的不同?高C币!!

问题描述 java socket客户端和Python socket客户端的不同?高C币!! 我们接的项目有一个java写的server,我只有它的文档,并且用java已经实现,但是现在要为 python实现,用java实现的代码: public static void main(String[] args) throws WindException, SendException, RecvException{ String host="172.22.128.16"; int port=

【Python之旅】第五篇(一):Python Socket通信原理

 只要和网络服务涉及的,就离不开Socket以及Socket编程,下面就说说Python Socket通信的基本原理. 1.Socket     socket也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求.可以列举中国移动或者是中国电信等的电话客服,当然,也可以看下面的图片来作形象的说明.     socket起源于Unix,而Unix/Linux基本哲学之一就是:一切皆文件,即都可以用&quo