基于RYU应用开发之负载均衡(源码开放)

本文介绍了如何在RYU上利用OpenFlow13的group table和select功能实现多路径传输,从而达到负载均衡。通过创建组表和设置队列,控制数据流经过不同路径,并通过调整权重分配流量,确保带宽的有效利用。此外,文章还展示了如何配置OpenvSwitch的队列以保障链路带宽。
摘要由CSDN通过智能技术生成

编者按:本文介绍的是如何在RYU上通过使用select group 来实现multipath,从而实现流量的调度,完成简单的负载均衡Demo。在OpenFlow13中有group table,可用于实现组播和冗余容灾等功能。实验中还使用了OpenvSwitch的队列queue完成了对链路带宽的保障。


要完成多径传输,那么网络拓扑必然有loop,所以首先要解决由于loop而可能产生的storm,解决方案在《基于SDNRYU应用开发之ARP代理》文中已经提出。

网络拓扑:

"""Custom loop topo example

   There are two paths between host1 and host2.

                |--------switch2 --------|

                |                        |

   host1 --- switch1                   switch4 -----host2

                |                        |   |------host3

                -------- switch3 ---------

                            |

                          host4

Adding the 'topos' dict with a key/value pair to generate our newly defined

topology enables one to pass in '--topo=mytopo' from the command line.

"""

from mininet.topo import Topo

class MyTopo(Topo):

    "Simple loop topology example."

    def __init__(self):

        "Create custom loop topo."

        # Initialize 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(switch1, host1, 1)

        self.addLink(switch1, switch2, 2, 1)

        self.addLink(switch1, switch3, 3, 1)

        self.addLink(switch2, switch4, 2, 1)

        self.addLink(switch3, switch4, 2, 2)

        self.addLink(switch4, host2, 3)

        self.addLink(switch4, host3, 4)

        #self.addLink(switch3, host4, 3)

topos = {'mytopo': (lambda: MyTopo())}

Multipath

解决网络可能形成风暴的问题之后,可以使用select类型的group_table来实现多径功能。

def send_group_mod(self, datapath):

    ofp = datapath.ofproto

    ofp_parser = datapath.ofproto_parser

    port_1 = 3

    actions_1 = [ofp_parser.OFPActionOutput(port_1)]

    port_2 = 2

    actions_2 = [ofp_parser.OFPActionOutput(port_2)]

    weight_1 = 50

    weight_2 = 50

    watch_port = ofproto_v1_3.OFPP_ANY

    watch_group = ofproto_v1_3.OFPQ_ALL

    buckets = [

        ofp_parser.OFPBucket(weight_1, watch_port, watch_group, actions_1),

        ofp_parser.OFPBucket(weight_2, watch_port, watch_group, actions_2)]

    group_id = 50

    req = ofp_parser.OFPGroupMod(

        datapath, ofp.OFPFC_ADD,

        ofp.OFPGT_SELECT, group_id, buckets)

datapath.send_msg(req)

不知道现在OVSselect

以下是使用Mininet和Ryu实现负载均衡的示例代码: 1. 在Mininet中创建拓扑 ``` sudo mn --topo linear,3 --mac --switch ovsk --controller remote ``` 2. 在Ryu中编写控制器代码 ``` from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER from ryu.controller.handler import set_ev_cls from ryu.ofproto import ofproto_v1_3 from ryu.lib.packet import packet, ethernet from ryu.lib.packet import ipv4, tcp, udp class LoadBalancer(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] def __init__(self, *args, **kwargs): super(LoadBalancer, self).__init__(*args, **kwargs) self.mac_to_port = {} @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def switch_features_handler(self, ev): datapath = ev.msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser # 模拟交换机上的流表 match = parser.OFPMatch() actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions) def add_flow(self, datapath, priority, match, actions): ofproto = datapath.ofproto parser = datapath.ofproto_parser # 安装流表项 inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst) datapath.send_msg(mod) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in_handler(self, ev): # 解析数据包 msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto parser = datapath.ofproto_parser in_port = msg.match['in_port'] pkt = packet.Packet(msg.data) eth = pkt.get_protocol(ethernet.ethernet) # 仅处理IP数据包 if eth.ethertype == ether_types.ETH_TYPE_IP: ip = pkt.get_protocol(ipv4.ipv4) # 仅处理TCP和UDP数据包 if ip.proto == in_proto.IPPROTO_TCP or ip.proto == in_proto.IPPROTO_UDP: tp = pkt.get_protocol(tcp.tcp) or pkt.get_protocol(udp.udp) # 计算哈希值 src_ip = ip.src dst_ip = ip.dst src_port = tp.src_port dst_port = tp.dst_port hash_val = hash((src_ip, dst_ip, src_port, dst_port)) % 3 # 根据哈希值选择输出端口 out_port = hash_val + 1 # 安装流表项,将数据包转发到相应的输出端口 actions = [parser.OFPActionOutput(out_port)] match = parser.OFPMatch(in_port=in_port, eth_type=eth.ethertype, ipv4_src=src_ip, ipv4_dst=dst_ip, ip_proto=ip.proto, tcp_src=src_port, tcp_dst=dst_port) self.add_flow(datapath, 1, match, actions) # 发送数据包到对应的交换机端口 out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions) datapath.send_msg(out) ``` 3. 运行控制器 ``` ryu-manager load_balancer.py ``` 4. 在Mininet中启动HTTP服务器 ``` h1 python -m SimpleHTTPServer 80 & h2 python -m SimpleHTTPServer 80 & h3 python -m SimpleHTTPServer 80 & ``` 5. 在浏览器中测试负载均衡 ``` http://<controller_ip>/h1 http://<controller_ip>/h2 http://<controller_ip>/h3 ``` 其中,`<controller_ip>`是控制器的IP地址,可以使用以下命令获取: ``` ifconfig ``` 这个示例代码将会根据哈希值将HTTP请求分配给3个主机中的一个,从而实现了负载均衡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值