1. 程式人生 > 實用技巧 >架構設計 | 分散式體系下,服務分層監控策略

架構設計 | 分散式體系下,服務分層監控策略

一、實驗目的 在實驗 2 的基礎上進一步熟悉 Mininet 自定義拓撲指令碼,以及與損耗率相關的設定;初步瞭解 Mininet 安裝時自帶的 POX 控制器指令碼編寫,測試路徑損耗率。 二、實驗任務

h0 向 h1 傳送資料包,由於在 Mininet 指令碼中設定了連線損耗率,在傳輸過程中會丟失一些包,本次實驗的目的是展示如何通過控制器計算路徑損耗速率(h0- s0-s1-h1)。這裡假設控制器預先知道網路拓撲。控制器將向 s0 和 s1 發 flow_stats_request,當控制器接收到來自 s0 的 response 時,將特定流的資料包數儲存在 input_pkts 中,當控制器接收到來自 s1 的 response 時,將接收到特定流的資料包數儲存在 output_pkts 中,差值就是丟失的資料包數量。 基於上述拓撲,編寫 Mininet 指令碼,設定特定的交換機間的路徑損耗速率,然後編寫 POX 控制器指令碼,實現對路徑的損耗率的測量。 三、實驗步驟
1. 實驗環境 安裝了 Ubuntu 16.04.5 Desktop amd64 的虛擬機器 2. 實驗過程 SDNLAB 實驗參考資料:https://www.sdnlab.com/15100.html (1)新建並編輯 pox 指令碼 flowstat.py,內容如下:
#!/usr/bin/python
# standard includes
from pox.core import core
from pox.lib.util import dpidToStr
import pox.openflow.libopenflow_01 as of
from pox.lib.addresses import
IPAddr, EthAddr # include as part of the betta branch from pox.openflow.of_json import * from pox.lib.recoco import Timer import time log = core.getLogger() src_dpid = 0 dst_dpid = 0 input_pkts = 0 output_pkts = 0 def getTheTime(): #fuction to create a timestamp flock = time.localtime() then
= "[%s-%s-%s" %(str(flock.tm_year),str(flock.tm_mon),str(flock.tm_mday)) if int(flock.tm_hour)<10: hrs = "0%s" % (str(flock.tm_hour)) else: hrs = str(flock.tm_hour) if int(flock.tm_min)<10: mins = "0%s" % (str(flock.tm_min)) else: mins = str(flock.tm_min) if int(flock.tm_sec)<10: secs = "0%s" % (str(flock.tm_sec)) else: secs = str(flock.tm_sec) then +="]%s.%s.%s" % (hrs,mins,secs) return then # handler for timer function that sends the requests to all the # switches connected to the controller. def _timer_func (): for connection in core.openflow._connections.values(): connection.send(of.ofp_stats_request(body=of.ofp_flow_stats_request())) connection.send(of.ofp_stats_request(body=of.ofp_port_stats_request())) log.debug("Sent %i flow/port stats request(s)", len(core.openflow._connections)) # handler to display flow statistics received in JSON format # structure of event.stats is defined by ofp_flow_stats() def _handle_flowstats_received (event): #stats = flow_stats_to_list(event.stats) #log.debug("FlowStatsReceived from %s: %s", dpidToStr(event.connection.dpid), stats) global src_dpid, dst_dpid, input_pkts, output_pkts #print "src_dpid=", dpidToStr(src_dpid), "dst_dpid=", dpidToStr(dst_dpid) for f in event.stats: if f.match.dl_type==0x0800 and f.match.nw_dst==IPAddr("192.168.123.2") and f.match.nw_tos==0x64 and event.connection.dpid==src_dpid: #print "input: ", f.byte_count, f.packet_count input_pkts = f.packet_count if f.match.dl_type==0x0800 and f.match.nw_dst==IPAddr("192.168.123.2") and f.match.nw_tos==0x64 and event.connection.dpid==dst_dpid: #print "output: ", f.byte_count, f.packet_count output_pkts = f.packet_count if input_pkts !=0: print getTheTime(), "Path Loss Rate =", (input_pkts-output_pkts)*1.0/input_pkts*100, "%" # handler to display port statistics received in JSON format def _handle_portstats_received (event): #print "\n<<<STATS-REPLY: Return PORT stats for Switch", event.connection.dpid,"at ",getTheTime() #for f in event.stats: #if int(f.port_no)<65534: #print " PortNo:", f.port_no, " Fwd's Pkts:", f.tx_packets, " Fwd's Bytes:", f.tx_bytes, " Rc'd Pkts:", f.rx_packets, " Rc's Bytes:", f.rx_bytes #print " PortNo:", f.port_no, " TxDrop:", f.tx_dropped, " RxDrop:", f.rx_dropped, " TxErr:", f.tx_errors, " RxErr:", f.rx_errors, " CRC:", f.rx_crc_err, " Coll:", f.collisions stats = flow_stats_to_list(event.stats) log.debug("PortStatsReceived from %s: %s", dpidToStr(event.connection.dpid), stats) def _handle_ConnectionUp (event): global src_dpid, dst_dpid print "ConnectionUp: ", dpidToStr(event.connection.dpid) for m in event.connection.features.ports: if m.name == "s0-eth0": src_dpid = event.connection.dpid elif m.name == "s1-eth0": dst_dpid = event.connection.dpid msg = of.ofp_flow_mod() msg.priority =1 msg.idle_timeout = 0 msg.match.in_port =1 msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL)) event.connection.send(msg) msg = of.ofp_flow_mod() msg.priority =1 msg.idle_timeout = 0 msg.match.in_port =2 msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL)) event.connection.send(msg) msg = of.ofp_flow_mod() msg.priority =10 msg.idle_timeout = 0 msg.hard_timeout = 0 msg.match.dl_type = 0x0800 msg.match.nw_tos = 0x64 msg.match.in_port=1 msg.match.nw_dst = "192.168.123.2" msg.actions.append(of.ofp_action_output(port = 2)) event.connection.send(msg) msg = of.ofp_flow_mod() msg.priority =10 msg.idle_timeout = 0 msg.hard_timeout = 0 msg.match.dl_type = 0x0800 msg.match.nw_tos = 0x64 msg.match.nw_dst = "192.168.123.1" msg.actions.append(of.ofp_action_output(port = 1)) event.connection.send(msg) # main functiont to launch the module def launch (): # attach handsers to listners core.openflow.addListenerByName("FlowStatsReceived", _handle_flowstats_received) core.openflow.addListenerByName("PortStatsReceived", _handle_portstats_received) core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp) # timer set to execute every five seconds Timer(1, _timer_func, recurring=True)

在 pox 安裝目錄下(Mininet 完整安裝包含了 pox)執行以下命令執行 pox 指令碼

$ ./pox.py flowstat

(2)編輯 Mininet 指令碼 mymininet3.py 參照拓撲圖,新建並編輯 Mininet 指令碼 mymininet3.py。 控制器因為安裝在本機,所以需修改參考資料程式碼中的控制器地址為 127.0.0.1:6633。 switch.cmd( 'ovs-vsctl set-controller dp0 tcp:127.0.0.1:6633' ) switch1.cmd( 'ovs-vsctl set-controller dp1 tcp:127.0.0.1:6633' ) 設定 s0 和 s1 之間鏈路的丟包率為 0info( "*** Creating links\n" ) linkopts0=dict(bw=100, delay='1ms', loss=0) linkopts1=dict(bw=100, delay='1ms', loss=0) link0=TCLink( h0, switch, **linkopts0) link1 = TCLink( switch, switch1, **linkopts1) link2 = TCLink( h1, switch1, **linkopts0) 具體程式碼如下
#!/usr/bin/python
 
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import TCLink
from mininet.log import  setLogLevel, info
from threading import Timer
from mininet.util import quietRun
from time import sleep
 
def myNet(cname='controller', cargs='-v ptcp:'):
    "Create network from scratch using Open vSwitch."
    info( "*** Creating nodes\n" )
    controller = Node( 'c0', inNamespace=False )
    switch = Node( 's0', inNamespace=False )
    switch1 = Node( 's1', inNamespace=False )
    h0 = Node( 'h0' )
    h1 = Node( 'h1' )
    
    info( "*** Creating links\n" )
    linkopts0=dict(bw=100, delay='1ms', loss=0)
    linkopts1=dict(bw=100, delay='1ms', loss=0)
    link0=TCLink( h0, switch, **linkopts0)
    link1 = TCLink( switch, switch1, **linkopts1)     
    link2 = TCLink( h1, switch1, **linkopts0)
    #print link0.intf1, link0.intf2
    link0.intf2.setMAC("0:0:0:0:0:1")
    link1.intf1.setMAC("0:0:0:0:0:2")
    link1.intf2.setMAC("0:1:0:0:0:1") 
    link2.intf2.setMAC("0:1:0:0:0:2")
 
    info( "*** Configuring hosts\n" )
    h0.setIP( '192.168.123.1/24' )
    h1.setIP( '192.168.123.2/24' )
       
    info( "*** Starting network using Open vSwitch\n" )
    switch.cmd( 'ovs-vsctl del-br dp0' )
    switch.cmd( 'ovs-vsctl add-br dp0' )
    switch1.cmd( 'ovs-vsctl del-br dp1' )
    switch1.cmd( 'ovs-vsctl add-br dp1' )
 
    controller.cmd( cname + ' ' + cargs + '&' )     
    for intf in switch.intfs.values():
        print intf
        print switch.cmd( 'ovs-vsctl add-port dp0 %s' % intf )
    for intf in switch1.intfs.values():
        print intf
        print switch1.cmd( 'ovs-vsctl add-port dp1 %s' % intf )
   
    # Note: controller and switch are in root namespace, and we
    # can connect via loopback interface
    switch.cmd( 'ovs-vsctl set-controller dp0 tcp:127.0.0.1:6633' )
    switch1.cmd( 'ovs-vsctl set-controller dp1 tcp:127.0.0.1:6633' )
  
    info( '*** Waiting for switch to connect to controller' )
    while 'is_connected' not in quietRun( 'ovs-vsctl show' ):
        sleep( 1 )
        info( '.' )
    info( '\n' )
 
    #info( "*** Running test\n" )
    h0.cmdPrint( 'ping -Q 0x64 -c 20 ' + h1.IP() )
    
    sleep( 1 ) 
    info( "*** Stopping network\n" )
    controller.cmd( 'kill %' + cname )
    switch.cmd( 'ovs-vsctl del-br dp0' )
    switch.deleteIntfs()
    switch1.cmd( 'ovs-vsctl del-br dp1' )
    switch1.deleteIntfs()
    info( '\n' )
 
if __name__ == '__main__':
    setLogLevel( 'info' )
    info( '*** Scratch network demo (kernel datapath)\n' )
    Mininet.init()
    myNet()

再執行命令執行 Mininet 指令碼 mymininet3.py

$ sudo python mymininet3.py Ping 預設是每 1 秒鐘測一次,ping 的結果會顯示一個丟包率,這裡的丟包率是根據 ping 不通的次數佔總次數的百分比計算得到的。上圖中由於一共 ping 了 20 次,每次都能通,所以丟包率是 0。

觀察 pox 側的實時狀態更新平均丟包率為 0,結果符合 Mininet 指令碼中設定的損耗率,也有可能出現負值,可以認為沒有丟包。

修改程式碼中 s0 和 s1 之間鏈路的丟包率為 10。 info( "*** Creating links\n" ) linkopts0=dict(bw=100, delay='1ms', loss=0) linkopts1=dict(bw=100, delay='1ms', loss=10) link0=TCLink( h0, switch, **linkopts0) link1 = TCLink( switch, switch1, **linkopts1) link2 = TCLink( h1, switch1, **linkopts0) 重新執行 Mininet 指令碼 mymininet3.py,20 秒時間的 ping 過程中有 icmp_seq 為 3/7/15/18/20 共 5次 ping 不通,所以丟包率計算為 25%。

POX 端重新測試,會發現出現丟包現象,但是實際測量出的丟包率會有浮動,鏈路的效能總體受到了限制。

四、實驗遇到的問題

無法直接在 pox 目錄下新建 py 檔案

解決方法:使用程式碼建立

$ cd pox

$ sudo touch flow_stats.py

$ sudo gedit flow_stats.py

$ nano flow_stats.py