负载均衡(Load Balance)的意思是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等,从而协同完成工作任务。如果存在更多的数据包同时通过网络连向一台服务器, 也就是网络的速度比网络所连接的设备速度快的情况下,负载均衡技术是解决这个问题的有效方式。负载均衡是一种扩展现有网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性的技术。
在此拓扑结构中,h1是客户端,服务器端h2,h3,h4上各自有不同的服务。我们要实现一个负载均衡的北向程序,当h2,h1,h3向h1传输数据时,北向应用根据链路的使用状况动态的调整路由规则。例如:s1-s4链路带宽充足情况下应默认s4-s1的传输路径,当剩余带宽不足的情况下应动态调整路由,使链路负载达到平衡。
https://www.cnblogs.com/gs-23/p/12156503.html
MyTopo.py,运行:sudo mn --custom MyTopo.py --topo mytopo --controller remote -x --switch ovsk,protocols=OpenFlow13
from mininet.topo import Topo class MyTopo( Topo ): def __init__( self ): # initilaize topology Topo.__init__( self ) # add hosts and switches host1 = self.addHost( 'h1' ) host2 = self.addHost( 'h2' ) host3 = self.addHost( 'h3' ) host4 = self.addHost( 'h4' ) switch1 = self.addSwitch( 's1' ) switch2 = self.addSwitch( 's2' ) switch3 = self.addSwitch( 's3' ) switch4 = self.addSwitch( 's4' ) # add links self.addLink(host1,switch1) self.addLink(switch1,switch2) self.addLink(switch1,switch3) self.addLink(switch1,switch4) self.addLink(switch2,switch4) self.addLink(switch3,switch4) self.addLink(switch4,host2) self.addLink(switch4,host3) self.addLink(switch4,host4) topos = { 'mytopo': ( lambda: MyTopo() ) }
controller.py
# encoding: utf-8 import httplib2 import time import json class OdlUtil: url = '' def __init__(self, host, port): self.url = 'http://' + host + ':' + str(port) def install_flow(self, container_name='default',username="admin", password="admin"): http = httplib2.Http() http.add_credentials(username, password) headers = {'Accept': 'application/json'} flow_name = 'flow_' + str(int(time.time()*1000)) #s2流表 #h2工作时s2端口1流量空闲时下发的流表 h2_to_s2_1 ='{"flow": [{"id": "0","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.2/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "1"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "1","table_id": "0"}]}' #h3工作时s2端口1流量空闲时下发的流表 h3_to_s2_1 ='{"flow": [{"id": "1","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "1"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "1","table_id": "0"}]}' mh3_to_s2_1 ='{"flow": [{"id": "1","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "1"},"order": "0"}]}}]},'\ '"priority": "100","cookie": "1","table_id": "0"}]}' #h3工作时s2端口1流量满载时下发的流表 h3_to_s2_2 ='{"flow": [{"id": "2","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "2"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "1","table_id": "0"}]}' mh3_to_s2_2 ='{"flow": [{"id": "2","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "2"},"order": "0"}]}}]},'\ '"priority": "100","cookie": "1","table_id": "0"}]}' #s3流表 s3_1='{"flow": [{"id": "0","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "1"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "1","table_id": "0"}]}' s3_2='{"flow": [{"id": "1","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "2"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "2","table_id": "0"}]}' #s1流表 s1_2To1='{"flow": [{"id": "0","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.2/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "1"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "1","table_id": "0"}]}' s1_3To1='{"flow": [{"id": "1","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.3/32","ipv4-destination": "10.0.0.1/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "1"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "1","table_id": "0"}]}' #h1工作时s1端口2流量空闲时下发的流表 h1_to_s1_2 ='{"flow": [{"id": "2","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "2"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "2","table_id": "0"}]}' mh1_to_s1_2 ='{"flow": [{"id": "3","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "2"},"order": "0"}]}}]},'\ '"priority": "100","cookie": "3","table_id": "0"}]}' #h1工作时s1端口2流量满载时下发的流表 h1_to_s1_3 ='{"flow": [{"id": "2","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "3"},"order": "0"}]}}]},'\ '"priority": "101","cookie": "2","table_id": "0"}]}' mh1_to_s1_3 ='{"flow": [{"id": "3","match": {"ethernet-match":'\ '{"ethernet-type": {"type": "2048"}},'\ '"ipv4-source":"10.0.0.1/32","ipv4-destination": "10.0.0.3/32"},'\ '"instructions": {"instruction": [{"order": "0",'\ '"apply-actions": {"action": [{"output-action": {'\ '"output-node-connector": "3"},"order": "0"}]}}]},'\ '"priority": "100","cookie": "3","table_id": "0"}]}' headers = {'Content-type': 'application/json'} num=0 #下发流表,地址由ODL上获得 #下发s1与s3的流表 response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/0', body=s1_2To1, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/1', body=s1_3To1, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:3/flow-node-inventory:table/0/flow/0', body=s3_1, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:3/flow-node-inventory:table/0/flow/0', body=s3_2, method='PUT',headers=headers) #s2调用h2到1的流表 response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/0', body=h2_to_s2_1, method='PUT',headers=headers) while num < 4 : s1_uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:1/node-connector/openflow:1:2' s2_uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:1' #获取s1端口2的流量 response, content = http.request(uri=s1_uri, method='GET') content = json.loads(content.decode()) statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics'] s1_bytes1 = statistics['bytes']['transmitted'] #0.5秒后再次获取 time.sleep(0.5) response, content = http.request(uri=s1_uri, method='GET') content = json.loads(content.decode()) statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics'] s1_bytes2 = statistics['bytes']['transmitted'] s1_speed=float(s1_bytes2-s1_bytes1)/0.5 if s1_speed !=0 :#获取有效的速度 print ('s1端口2速度:') print (s1_speed) #在检测到s1端口2流量空闲时发的流表 if s1_speed < 1000 : print(' s1端口2空闲,h1数据包改为往s1端口2通过') response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/2', body=h1_to_s1_2, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/3', body=mh1_to_s1_2, method='PUT',headers=headers) #在检测到s1端口2流量满载时发的流表 else : print(' s1端口2满载,h1数据包改为往s1端口3通过') response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/2', body=h1_to_s1_3, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/flow-node-inventory:table/0/flow/3', body=mh1_to_s1_3, method='PUT',headers=headers) #获取s2端口1的流量 response, content = http.request(uri=s2_uri, method='GET') content = json.loads(content.decode()) statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics'] s2_bytes1 = statistics['bytes']['transmitted'] #0.5秒后再次获取 time.sleep(0.5) response, content = http.request(uri=s2_uri, method='GET') content = json.loads(content.decode()) statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics'] s2_bytes2 = statistics['bytes']['transmitted'] s2_speed=float(s2_bytes2-s2_bytes1)/0.5 if s2_speed !=0 :#获取有效的速度 print ('s2端口1速度:') print (s2_speed) #在检测到s2端口1流量空闲时发的流表 if s2_speed < 1000 : print(' s2端口1空闲,h3数据包改为往s2端口1通过') response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/1', body=h3_to_s2_1, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/2', body=mh3_to_s2_2, method='PUT',headers=headers) #在检测到s2端口1流量满载时发的流表 else : print(' s2端口1满载,h3数据包改为往s2端口2通过') response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/1', body=mh3_to_s2_1, method='PUT',headers=headers) response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:2/flow-node-inventory:table/0/flow/2', body=h3_to_s2_2, method='PUT',headers=headers) odl = OdlUtil('127.0.0.1', '8181') odl.install_flow()
sudo ovs-ofctl -O OpenFlow13 dump-flows s1
查看交换机流表命令:在termail中执行,与执行新建mininet一样。