219 SDN大作业:负载均衡
1.小组成员与分工
学号 | 姓名 | 分工 | 贡献比例 |
---|---|---|---|
031702526 | 周华 | ppt制作 | 20% |
031702514 | 严喜 | 写博客 | 20% |
031702533 | 吕瑞峰 | 写代码 | 30% |
031702542 | 林小棠 | 视频录制、ppt演示、写代码 | 30% |
2.拓扑搭建
拓扑图
拓扑脚本:
from mininet.topo import Topo
class MyTopo( Topo ):
"Simple topology example."
def __init__( self ):
"Create custom topo."
# Initialize topology
Topo.__init__( self )
# add hosts and switches
host1 = self.addHost( 'h1' )
host2 = self.addHost( 'h2' )
host3 = self.addHost( 'h3' )
switch1 = self.addSwitch( 's1' )
switch2 = self.addSwitch( 's2' )
switch3 = self.addSwitch( 's3' )
# add links
self.addLink(host1,switch1)
self.addLink(switch1,switch2)
self.addLink(switch1,switch3)
self.addLink(switch2,host2)
self.addLink(switch2,host3)
self.addLink(switch2,switch3)
topos = { 'mytopo': ( lambda: MyTopo() ) }
负载均衡代码:
# -*- coding: 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))
#s3流表
s3_h3_to_h1='{"flow": [{"id": "0","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.3/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "1"}}]}}]},'
'"priority": "100","table_id": "0"}]}'
#s1流表
s1_h2_to_h1='{"flow": [{"id": "0","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.2/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "1"}}]}}]},'
'"priority": "100","table_id": "0"}]}'
s1_h3_to_h1='{"flow": [{"id": "0","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.3/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "1"}}]}}]},'
'"priority": "100","table_id": "0"}]}'
#s2流表
#h2工作下发的流表
s2_h2_to_h1='{"flow": [{"id": "0","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.2/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "1"}}]}}]},'
'"priority": "100","table_id": "0"}]}'
#h3工作时s2端口1空闲下发的流表
s2_h3_to_h1_1='{"flow": [{"id": "1","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.3/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "1"}}]}}]},'
'"priority": "101","table_id": "0"}]}'
s2_h3_to_h1_4='{"flow": [{"id": "2","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.3/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "4"}}]}}]},'
'"priority": "100","table_id": "0"}]}'
#h3工作时s2端口1满载下发的流表
s2_mh3_to_h1_1='{"flow": [{"id": "1","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.3/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "1"}}]}}]},'
'"priority": "100","table_id": "0"}]}'
s2_mh3_to_h1_4='{"flow": [{"id": "2","match": {"ethernet-match": '
'{"ethernet-type": {"type": "0x0800"}},'
'"ipv4-source": "10.0.0.3/32",'
'"ipv4-destination": "10.0.0.1/32"},'
'"instructions": {"instruction": [{"order": "0",'
'"apply-actions": {"action": [{"order": "0","output-action": {'
'"output-node-connector": "4"}}]}}]},'
'"priority": "101","table_id": "0"}]}'
headers = {'Content-type': 'application/json'}
#下发s1的流表
response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/opflow:1/flow-node-inventory:table/0/flow/0', body=s1_h2_to_h1, method='PUT',headers=headers)
response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/opflow:1/flow-node-inventory:table/0/flow/1', body=s1_h3_to_h1, method='PUT',headers=headers)
#下发s3的流表
response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/opflow:3/flow-node-inventory:table/0/flow/0', body=s3_h3_to_h1, method='PUT',headers=headers)
#下发s2的流表(h2到h1)
response, content = http.request(uri='http://127.0.0.1:8181/restconf/config/opendaylight-inventory:nodes/node/opflow:2/flow-node-inventory:table/0/flow/0', body=s2_h2_to_h1, method='PUT',headers=headers)
while True:
#获取s2端口1的流量
uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:1'
response, content = http.request(uri=uri, method='GET')
content = json.loads(content)
statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
bytes1_port1 = statistics['bytes']['transmitted']
#获取s2端口4的流量
uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:4'
response, content = http.request(uri=uri, method='GET')
content = json.loads(content)
statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
bytes1_port4 = statistics['bytes']['transmitted']
#2秒后再次获取
time.sleep(2)
uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:1'
response, content = http.request(uri=uri, method='GET')
content = json.loads(content)
statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
bytes2_port1 = statistics['bytes']['transmitted']
uri = 'http://127.0.0.1:8181/restconf/operational/opendaylight-inventory:nodes/node/openflow:2/node-connector/openflow:2:4'
response, content = http.request(uri=uri, method='GET')
content = json.loads(content)
statistics = content['node-connector'][0]['opendaylight-port-statistics:flow-capable-node-connector-statistics']
bytes2_port4 = statistics['bytes']['transmitted']
#输出s2端口1和端口4的速度
speed1=float(bytes2_port1-bytes1_port1)/2
speed2=float(bytes2_port4-bytes1_port4)/2
#在检测到s2的1口流量空闲时发的流表
if speed1 !=0 :#获取有效的速度
print('s2端口1速度:%.3lf byte/s' % speed1)
print('s2端口4速度:%.3lf byte/s' % speed2)
if speed1 < 2000 :
print('当前s2端口1处于空闲状态,h3数据包通往s1')
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=s2_h3_to_h1_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=s2_h3_to_h1_4, method='PUT',headers=headers)
#在检测到s2的1口流量满载时发的流表
else :
print('当前s2端口1处于满载状态,h3数据包通往s3')
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=s2_mh3_to_h1_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=s2_mh3_to_h1_1, method='PUT',headers=headers)
odl = OdlUtil('127.0.0.1', '8181')
odl.install_flow()
3.场景
服务器h2 h3上各自有不同的服务,h1是客户端。实现一个负载均衡的北向程序,当h2和h3向h1传输数据时,北向应用根据链路的使用状况动态的调整路由规则。
例如:当h2向h1使用s1-s2链路达到满负荷状态下,h3向h1的传输路径应该动态的调整为s3所在路径,而当h2停止向h1传输数据时,h3应调整回s1-s2路径。
4.作业演示视频
https://pan.baidu.com/s/1KSnN1I4LLhqwd8U7Vc6deA