A. 怎麼在linux上安裝receiver
首先來在CentOS5.5上安裝最新版Citrix Receiver 11.100。
1、安裝ICAClient(可以看到,缺少部分依賴包,主要用於GUI顯示介面),可以使用yum install libXaw.so.7來安裝依賴包,其他類似
2、安裝完成以後,可以在Application->Internet->Citrix Receiver打開
3、配置Citrix Receiver連接伺服器
4、添加XenApp或者XenDesktop伺服器,並配置地址
5、配置地址完成後,選擇View->Citrix XenApp View可以查看該伺服器的應用程序
6、點擊應用程序以後,會提示輸入賬號密碼,當然也支持Pass-Through方式。具體的配置請大家自行查看。
B. Linux進程通信實驗(共享內存通信,接上篇)
這一篇記錄一下共享內存實驗,需要linux的共享內存機制有一定的了解,同時也需要了解POSIX信號量來實現進程間的同步。可以參考以下兩篇博客: https://blog.csdn.net/sicofield/article/details/10897091
https://blog.csdn.net/ljianhui/article/details/10253345
實驗要求:編寫sender和receiver程序,sender創建一個共享內存並等待用戶輸入,然後把輸入通過共享內存發送給receiver並等待,receiver收到後把消息顯示在屏幕上並用同樣方式向sender發送一個over,然後兩個程序結束運行。
這個實驗的難點主要在於共享內存的創建和撤銷(涉及到的步驟比較多,需要理解各步驟的功能),以及實現兩個進程間的相互等待(使用信號量來實現,這里使用了有名信號量)
實驗心得:學習理解了linux的共享內存機制以及POSIX信號量機制。
兩個實驗雖然加強了對linux一些機制的理解,但是感覺對linux的學習還不夠,需要繼續學習。
C. 2020-08-25
Prometheus 實現郵件告警(Prometheus+Alertmanager+QQ郵箱或者網易163郵箱,目前測試過這兩種郵箱都可以發送告警郵件)
Prometheus實現郵件告警原理如下:
Prometheus官方有一個附帶的中間件:alertmanager,通過設置rules規則和路由轉發可以實現郵件告警,前提是你需要有一個可以發送郵件的郵件服務端(可以自建或者使用互聯網公司提供的免費郵箱)
告警原理圖
Prometheus完整架構圖
我之前得出的錯誤結論如下:
推薦直接在虛擬機操作系統上直接安裝Prometheus和Alertmanager,不推薦其中任何一方在容器中運行,因為測試過在容器中運行Prometheus和alertmanager,結果出現如下錯誤情況
第一種情況是:我的node-exporter掉線跌機了(手動關機,模擬突然掉線跌機),Prometheus卻提示節點依然在線?有時候卻能夠正常顯示節點掉線跌機,生成告警發送郵件
第二種情況是:我的node-exporter掉線跌機了(手動關機,模擬突然掉線跌機),Prometheus提示節點掉線,告警生成,但是沒有發送郵件,我手動恢復node-exporter後,告警解除,郵件能正常發送郵件提示告警已經解除。。。。
第三種情況是:我的node-exporter掉線跌機了(手動關機,模擬突然掉線跌機),Prometheus提示節點掉線,告警生成,正常成功發送郵件,我手動恢復node-exporter後,告警解除,郵件沒有發送出來。。。。
以上三種情況之前經常出現,當時第一步以為是自己設置的scrape_interval不合理導致的,結果調試幾次,問題沒有解決,第二步以為是自己的伺服器時間沒有做到精確同步,然後我去設置和阿里雲的ntp伺服器同步,結果問題依然沒有解決,第三步,換個方向,把alertmanager遷移到虛擬機操作系統上安裝運行,問題解決!
北京時間是GMT+8小時,有些同志的時間可能是UTC的,但是如果是在要求不太十分精確的情況下,UTC時間是剛剛好等於GMT時間
為了避免時區的混亂,prometheus所有的組件內部都強制使用Unix時間,對外展示使用GMT時間。
要改時區有兩個辦法
1 .修改源碼,重新編譯。
2. 使用 docker 運行 Prometheus,掛載本地時區文件
docker run --restart always -e TZ=Asia/Shanghai --hostname prometheus --name prometheus-server -d -p 9090:9090 -v /data/prometheus/server/data:/prometheus -v /data/prometheus/server/conf/prometheus.yml:/etc/prometheus/prometheus.yml -u root prom/prometheus:v2.5.0
正文開始
安裝alertmanager
容器安裝方式:
docker run -d --name alertmanager -p 9093:9093 -v /usr/local/Prometheus/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml prom/alertmanager:latest
先在宿主機/usr/local/Prometheus下創建一個文件夾alertmanager,然後在文件夾里創建alertmanager.yml配置文件,待會才能映射到alertmanager容器里的/etc/alertmanager目錄下
global:全局配置
resolve_timeout: 問題解決的超時時間
smtp_from: 發送告警郵件的郵箱賬號
smtp_smarthost: 郵箱 SMTP 服務地址,這里是以QQ郵箱為例,也可以用網易163郵箱,這個和我之前設置zabbix郵件告警時的配置一樣
smtp_auth_username: 如果沒有設置郵箱別名,那就是賬戶名
smtp_auth_password: 郵箱的授權碼,不是 賬戶密碼,你可以在QQ郵箱或者網易163郵箱網頁端設置,開啟 POP3/SMTP 服務時會提示,和配置zabbix郵件告警的時候幾乎一樣
smtp_require_tls: 是否使用 tls,根據環境不同,來選擇開啟和關閉。如果提示報錯 email.loginAuth failed: 530 Must issue a STARTTLS command first,那麼就需要設置為 true。著重說明一下,如果開啟了 tls,提示報錯 starttls failed: x509: certificate signed by unknown authority,需要在 email_configs 下配置 insecure_skip_verify: true 來跳過 tls 驗證。
templates: 告警模板目錄,可以不編寫模板,有默認模板
Subject: '{{ template "email.default.subject" . }}'
html: '{{ template "email.default.html" . }}'
route:報警的分發設置
group_by:分組
group_wait: 分組等待時間
group_interval: 5m 每組時間間隔
repeat_interval: 10m 重復間隔
receiver: 接收方式,請注意!這里的名字要對應下面receivers中的任何一個名字,不然會報錯,這里其實就是選擇方式,有郵箱,企業微信,wehook,victorops等等
receivers:接受方式匯總,即告警方式匯總
例子:
receivers:
- name:'default-receiver'
email_configs:
- to:'[email protected]'
html: '{{ template "alert.html" . }}'
headers: { Subject: "[WARN] 報警郵件test"}
inhibit_rules: 抑制規則
當存在與另一組匹配的警報(源)時,抑制規則將禁用與一組匹配的警報(目標)。
包括源匹配和目標匹配
alertmanager官方是這樣說的
Inhibition
Inhibition is a concept of suppressing notifications for certain alerts if certain other alerts are already firing.
Example: An alert is firing that informs that an entire cluster is not reachable. Alertmanager can be configured to mute all other alerts concerning this cluster if that particular alert is firing. This prevents notifications for hundreds or thousands of firing alerts that are unrelated to the actual issue.
Inhibitions are configured through the Alertmanager's configuration file.
當存在與另一組匹配器匹配的警報(源)時,禁止規則會使與一組匹配器匹配的警報(目標)靜音。目標警報和源警報的equal列表中的標簽名稱都必須具有相同的標簽值。
在語義上,缺少標簽和帶有空值的標簽是同一件事。因此,如果equal源警報和目標警報都缺少列出的所有標簽名稱,則將應用禁止規則。
為了防止警報禁止自身,與規則的目標和源端 都 匹配的警報不能被警報(包括其本身)為真來禁止。但是,我們建議選擇目標匹配器和源匹配器,以使警報永遠不會同時匹配雙方。這很容易進行推理,並且不會觸發此特殊情況。
接著是規則rules
不解釋了,自己研究官方文檔
alertmanager的非容器安裝方式是
wget https://github.com/prometheus/alertmanager/releases/download/v0.20.0/alertmanager-0.20.0.linux-amd64.tar.gz
tar xf alertmanager-0.20.0.linux-amd64.tar.gz
mv alertmanager-0.20.0.linux-amd64 /usr/local/alertmanager
vim /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=alertmanager
Documentation=https://github.com/prometheus/alertmanager
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/alertmanager/alertmanager --config.file=/usr/local/alertmanager/alertmanager.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target
Alertmanager 安裝目錄下默認有 alertmanager.yml 配置文件,可以創建新的配置文件,在啟動時指定即可。
其餘方式和上面一樣
接著是Prometheus,我之前的博客里有寫了容器安裝和非容器安裝的方法,自己去翻閱
然後是在prometheus.yml里修改相關配置
首先去掉alertmanager的注釋,改成IP加你設置的埠號,默認是9093
接著在rule_files: 下面寫下規則文件的絕對路徑,可以是具體文件名,也可以是*,也可以分幾級文件,*默認是全部匹配
接著是被監控項的設置,這里設置完成可以在Prometheus網頁里的targets里看得到
請注意,這里設置的參數名字要和rule規則中設置的參數名字一模一樣,否則你的prometheus服務會無法啟動,然後報錯
如果不在特定的job下設置scrape_interval(優先順序高於全局),則默認採用gobal下的scrape_interval
最後模擬節點掉線,手動關閉node-exporter或者Cadvisor
docker stop node-exporter 或者容器ID
docker stop cadvisor 或者容器ID
或者把up{{job='prometheus'}} == 1 設置成1,反向設置,不用關掉服務,就可以看看告警成不成功
說明一下 Prometheus Alert 告警狀態有三種狀態:Inactive、Pending、Firing。
Inactive:非活動狀態,表示正在監控,但是還未有任何警報觸發。
Pending:表示這個警報必須被觸發。由於警報可以被分組、壓抑/抑制或靜默/靜音,所以等待驗證,一旦所有的驗證都通過,則將轉到 Firing 狀態。
Firing:將警報發送到 AlertManager,它將按照配置將警報的發送給所有接收者。一旦警報解除,則將狀態轉到 Inactive,如此循環。
沒有配置告警模板時的默認告警格式是這樣的
節點恢復後郵件告知是這樣的
寫了模板後是這樣的
還要重新映射模板文件夾路徑到alertmanager容器里的相對路徑,然後重啟alertmanager,當然,如果目錄下沒有模板文件,則不顯示
告警模板
在alertmanager.yml中修改相關設置
重啟alertmanager
docker restart alertmanager
最終效果不是很好
D. 如何查看linux下串口是否可用串口名稱等
1、查看串口是否可用,可以對串口發送數據比如對com1口,echo lyjie126 > /dev/ttyS0
2、查看串口名稱使用 ls -l /dev/ttyS* 一般情況下串口的名稱全部在dev下面,如果你沒有外插串口卡的話默認是dev下的ttyS* ,一般ttyS0對應com1,ttyS1對應com2,當然也不一定是必然的;
3、查看串口驅動:cat /proc/tty/drivers/serial
4、查看串口設備:dmesg | grep ttyS*
(4)linuxreceiver擴展閱讀
介面劃分標准
同步串列介面(英文:SynchronousSerialInterface,SSI)是一種常用的工業用通信介面。。
非同步串列是指UART(Universal Asynchronous Receiver/Transmitter),通用非同步接收/發送。UART是一個並行輸入成為串列輸出的晶元,通常集成在主板上。UART包含TTL電平的串口和RS232電平的串口。 TTL電平是3.3V的,而RS232是負邏輯電平,它定義+5~+12V為低電平,而-12~-5V為高電平,MDS2710、MDS SD4、EL805等是RS232介面,EL806有TTL介面。
串列介面按電氣標准及協議來分包括RS-232-C、RS-422、RS485等。RS-232-C、RS-422與RS-485標准只對介面的電氣特性做出規定,不涉及接插件、電纜或協議。
E. receiver for linux安裝在Centos里,使用自帶瀏覽器正常登錄虛擬桌面,之後無法退出
控制下的暫停啊 掛起就行吧
F. 在Linux 上,編寫一個每秒接收 100萬UDP數據包的程序究竟有多難
首先,我們假設:
測量每秒的數據包(pps)比測量每秒位元組數(Bps)更有意思。您可以通過更好的管道輸送以及發送更長數據包來獲取更高的Bps。而相比之下,提高pps要困難得多。
因為我們對pps感興趣,我們的實驗將使用較短的 UDP 消息。准確來說是 32 位元組的 UDP 負載,這相當於乙太網層的 74 位元組。
在實驗中,我們將使用兩個物理伺服器:「接收器」和「發送器」。
它們都有兩個六核2 GHz的 Xeon處理器。每個伺服器都啟用了 24 個處理器的超線程(HT),有 Solarflare 的 10G 多隊列網卡,有 11 個接收隊列配置。稍後將詳細介紹。
測試程序的源代碼分別是:udpsender、udpreceiver。
預備知識
我們使用4321作為UDP數據包的埠,在開始之前,我們必須確保傳輸不會被iptables干擾:
Shell
receiver$ iptables -I INPUT 1 -p udp --dport 4321 -j ACCEPT
receiver$ iptables -t raw -I PREROUTING 1 -p udp --dport 4321 -j NOTRACK
為了後面測試方便,我們顯式地定義IP地址:
Shell
receiver$ for i in `seq 1 20`; do
ip addr add 192.168.254.$i/24 dev eth2;
done
sender$ ip addr add 192.168.254.30/24 dev eth3
1. 簡單的方法
開始我們做一些最簡單的試驗。通過簡單地發送和接收,有多少包將會被傳送?
模擬發送者的偽代碼:
Python
fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
fd.bind(("0.0.0.0", 65400)) # select source port to rece nondeterminism
fd.connect(("192.168.254.1", 4321))
while True:
fd.sendmmsg(["x00" * 32] * 1024)
因為我們使用了常見的系統調用的send,所以效率不會很高。上下文切換到內核代價很高所以最好避免它。幸運地是,最近Linux加入了一個方便的系統調用叫sendmmsg。它允許我們在一次調用時,發送很多的數據包。那我們就一次發1024個數據包。
模擬接受者的偽代碼:
Python
fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
fd.bind(("0.0.0.0", 4321))
while True:
packets = [None] * 1024
fd.recvmmsg(packets, MSG_WAITFORONE)
同樣地,recvmmsg 也是相對於常見的 recv 更有效的一版系統調用。
讓我們試試吧:
Shell
sender$ ./udpsender 192.168.254.1:4321
receiver$ ./udpreceiver1 0.0.0.0:4321
0.352M pps 10.730MiB / 90.010Mb
0.284M pps 8.655MiB / 72.603Mb
0.262M pps 7.991MiB / 67.033Mb
0.199M pps 6.081MiB / 51.013Mb
0.195M pps 5.956MiB / 49.966Mb
0.199M pps 6.060MiB / 50.836Mb
0.200M pps 6.097MiB / 51.147Mb
0.197M pps 6.021MiB / 50.509Mb
測試發現,運用最簡單的方式可以實現 197k – 350k pps。看起來還不錯嘛,但不幸的是,很不穩定啊,這是因為內核在核之間交換我們的程序,那我們把進程附在 CPU 上將會有所幫助
Shell
sender$ taskset -c 1 ./udpsender 192.168.254.1:4321
receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
0.362M pps 11.058MiB / 92.760Mb
0.374M pps 11.411MiB / 95.723Mb
0.369M pps 11.252MiB / 94.389Mb
0.370M pps 11.289MiB / 94.696Mb
0.365M pps 11.152MiB / 93.552Mb
0.360M pps 10.971MiB / 92.033Mb
現在內核調度器將進程運行在特定的CPU上,這提高了處理器緩存,使數據更加一致,這就是我們想要的啊!
2. 發送更多的數據包
雖然 370k pps 對於簡單的程序來說已經很不錯了,但是離我們 1Mpps 的目標還有些距離。為了接收更多,首先我們必須發送更多的包。那我們用獨立的兩個線程發送,如何呢:
Shell
sender$ taskset -c 1,2 ./udpsender
192.168.254.1:4321 192.168.254.1:4321
receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
0.349M pps 10.651MiB / 89.343Mb
0.354M pps 10.815MiB / 90.724Mb
0.354M pps 10.806MiB / 90.646Mb
0.354M pps 10.811MiB / 90.690Mb
接收一端的數據沒有增加,ethtool –S 命令將顯示數據包實際上都去哪兒了:
Shell
receiver$ watch 'sudo ethtool -S eth2 |grep rx'
rx_nodesc_drop_cnt: 451.3k/s
rx-0.rx_packets: 8.0/s
rx-1.rx_packets: 0.0/s
rx-2.rx_packets: 0.0/s
rx-3.rx_packets: 0.5/s
rx-4.rx_packets: 355.2k/s
rx-5.rx_packets: 0.0/s
rx-6.rx_packets: 0.0/s
rx-7.rx_packets: 0.5/s
rx-8.rx_packets: 0.0/s
rx-9.rx_packets: 0.0/s
rx-10.rx_packets: 0.0/s
通過這些統計,NIC 顯示 4 號 RX 隊列已經成功地傳輸大約 350Kpps。rx_nodesc_drop_cnt 是 Solarflare 特有的計數器,表明NIC發送到內核未能實現發送 450kpps。
有時候,這些數據包沒有被發送的原因不是很清晰,然而在我們這種情境下卻很清楚:4號RX隊列發送數據包到4號CPU,然而4號CPU已經忙不過來了,因為它最忙也只能讀350kpps。在htop中顯示為:
多隊列 NIC 速成課程
從歷史上看,網卡擁有單個RX隊列,用於硬體和內核之間傳遞數據包。這樣的設計有一個明顯的限制,就是不可能比單個CPU處理更多的數據包。
為了利用多核系統,NIC開始支持多個RX隊列。這種設計很簡單:每個RX隊列被附到分開的CPU上,因此,把包送到所有的RX隊列網卡可以利用所有的CPU。但是又產生了另一個問題:對於一個數據包,NIC怎麼決定把它發送到哪一個RX隊列?
用 Round-robin 的方式來平衡是不能接受的,因為這有可能導致單個連接中數據包的重排序。另一種方法是使用數據包的hash值來決定RX號碼。Hash值通常由一個元組(源IP,目標IP,源port,目標port)計算而來。這確保了從一個流產生的包將最終在完全相同的RX隊列,並且不可能在一個流中重排包。
在我們的例子中,hash值可能是這樣的:
Shell
1
RX_queue_number = hash('192.168.254.30', '192.168.254.1', 65400, 4321) % number_of_queues
多隊列 hash 演算法
Hash演算法通過ethtool配置,設置如下:
Shell
receiver$ ethtool -n eth2 rx-flow-hash udp4
UDP over IPV4 flows use these fields for computing Hash flow key:
IP SA
IP DA
對於IPv4 UDP數據包,NIC將hash(源 IP,目標 IP)地址。即
Shell
1
RX_queue_number = hash('192.168.254.30', '192.168.254.1') % number_of_queues
這是相當有限的,因為它忽略了埠號。很多NIC允許自定義hash。再一次,使用ethtool我們可以選擇元組(源 IP、目標 IP、源port、目標port)生成hash值。
Shell
receiver$ ethtool -N eth2 rx-flow-hash udp4 sdfn
Cannot change RX network flow hashing options: Operation not supported
不幸地是,我們的NIC不支持自定義,我們只能選用(源 IP、目的 IP) 生成hash。
NUMA性能報告
到目前為止,我們所有的數據包都流向一個RX隊列,並且一個CPU。我們可以借這個機會為基準來衡量不同CPU的性能。在我們設置為接收方的主機上有兩個單獨的處理器,每一個都是一個不同的NUMA節點。
在我們設置中,可以將單線程接收者依附到四個CPU中的一個,四個選項如下:
另一個CPU上運行接收器,但將相同的NUMA節點作為RX隊列。性能如上面我們看到的,大約是360 kpps。
將運行接收器的同一 CPU 作為RX隊列,我們可以得到大約430 kpps。但這樣也會有很高的不穩定性,如果NIC被數據包所淹沒,性能將下降到零。
當接收器運行在HT對應的處理RX隊列的CPU之上,性能是通常的一半,大約在200kpps左右。
接收器在一個不同的NUMA節點而不是RX隊列的CPU上,性能大約是330 kpps。但是數字會不太一致。
雖然運行在一個不同的NUMA節點上有10%的代價,聽起來可能不算太壞,但隨著規模的變大,問題只會變得更糟。在一些測試中,每個核只能發出250 kpps,在所有跨NUMA測試中,這種不穩定是很糟糕。跨NUMA節點的性能損失,在更高的吞吐量上更明顯。在一次測試時,發現在一個壞掉的NUMA節點上運行接收器,性能下降有4倍。
3.多接收IP
因為我們NIC上hash演算法的限制,通過RX隊列分配數據包的唯一方法是利用多個IP地址。下面是如何將數據包發到不同的目的IP:
1
sender$ taskset -c 1,2 ./udpsender 192.168.254.1:4321 192.168.254.2:4321
ethtool 證實了數據包流向了不同的 RX 隊列:
Shell
receiver$ watch 'sudo ethtool -S eth2 |grep rx'
rx-0.rx_packets: 8.0/s
rx-1.rx_packets: 0.0/s
rx-2.rx_packets: 0.0/s
rx-3.rx_packets: 355.2k/s
rx-4.rx_packets: 0.5/s
rx-5.rx_packets: 297.0k/s
rx-6.rx_packets: 0.0/s
rx-7.rx_packets: 0.5/s
rx-8.rx_packets: 0.0/s
rx-9.rx_packets: 0.0/s
rx-10.rx_packets: 0.0/s
接收部分:
Shell
receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
0.609M pps 18.599MiB / 156.019Mb
0.657M pps 20.039MiB / 168.102Mb
0.649M pps 19.803MiB / 166.120Mb
萬歲!有兩個核忙於處理RX隊列,第三運行應用程序時,可以達到大約650 kpps !
我們可以通過發送數據到三或四個RX隊列來增加這個數值,但是很快這個應用就會有另一個瓶頸。這一次rx_nodesc_drop_cnt沒有增加,但是netstat接收到了如下錯誤:
Shell
receiver$ watch 'netstat -s --udp'
Udp:
437.0k/s packets received
0.0/s packets to unknown port received.
386.9k/s packet receive errors
0.0/s packets sent
RcvbufErrors: 123.8k/s
SndbufErrors: 0
InCsumErrors: 0
這意味著雖然NIC能夠將數據包發送到內核,但是內核不能將數據包發給應用程序。在我們的case中,只能提供440 kpps,其餘的390 kpps + 123 kpps的下降是由於應用程序接收它們不夠快。
4.多線程接收
我們需要擴展接收者應用程序。最簡單的方式是利用多線程接收,但是不管用:
Shell
sender$ taskset -c 1,2 ./udpsender 192.168.254.1:4321 192.168.254.2:4321
receiver$ taskset -c 1,2 ./udpreceiver1 0.0.0.0:4321 2
0.495M pps 15.108MiB / 126.733Mb
0.480M pps 14.636MiB / 122.775Mb
0.461M pps 14.071MiB / 118.038Mb
0.486M pps 14.820MiB / 124.322Mb
接收性能較於單個線程下降了,這是由UDP接收緩沖區那邊的鎖競爭導致的。由於兩個線程使用相同的套接字描述符,它們花費過多的時間在UDP接收緩沖區的鎖競爭。這篇論文詳細描述了這一問題。
看來使用多線程從一個描述符接收,並不是最優方案。
5. SO_REUSEPORT
幸運地是,最近有一個解決方案添加到 Linux 了 —— SO_REUSEPORT 標志位(flag)。當這個標志位設置在一個套接字描述符上時,Linux將允許許多進程綁定到相同的埠,事實上,任何數量的進程將允許綁定上去,負載也會均衡分布。
有了SO_REUSEPORT,每一個進程都有一個獨立的socket描述符。因此每一個都會擁有一個專用的UDP接收緩沖區。這樣就避免了以前遇到的競爭問題:
Shell
1
2
3
4
receiver$ taskset -c 1,2,3,4 ./udpreceiver1 0.0.0.0:4321 4 1
1.114M pps 34.007MiB / 285.271Mb
1.147M pps 34.990MiB / 293.518Mb
1.126M pps 34.374MiB / 288.354Mb
現在更加喜歡了,吞吐量很不錯嘛!
更多的調查顯示還有進一步改進的空間。即使我們開始4個接收線程,負載也會不均勻地分布:
兩個進程接收了所有的工作,而另外兩個根本沒有數據包。這是因為hash沖突,但是這次是在SO_REUSEPORT層。
結束語
我做了一些進一步的測試,完全一致的RX隊列,接收線程在單個NUMA節點可以達到1.4Mpps。在不同的NUMA節點上運行接收者會導致這個數字做多下降到1Mpps。
總之,如果你想要一個完美的性能,你需要做下面這些:
確保流量均勻分布在許多RX隊列和SO_REUSEPORT進程上。在實踐中,只要有大量的連接(或流動),負載通常是分布式的。
需要有足夠的CPU容量去從內核上獲取數據包。
To make the things harder, both RX queues and receiver processes should be on a single NUMA node.
為了使事情更加穩定,RX隊列和接收進程都應該在單個NUMA節點上。
雖然我們已經表明,在一台Linux機器上接收1Mpps在技術上是可行的,但是應用程序將不會對收到的數據包做任何實際處理——甚至連看都不看內容的流量。別太指望這樣的性能,因為對於任何實際應用並沒有太大用處。
G. 如何在ubuntu安裝receiver 13.6 for linux
有以下方法:
方法一:
使用Linux系統上支持Windows程序運行的用Wine程序。
方法二:
使用用虛擬機,如VMware、VirtualBox等,在虛擬機上安裝Windows的虛擬機系統,然後再在虛擬機系統裡面安裝Windows應用程序即可。
上面兩種方法對比:第一種方法對於某些Windows程序不支持,第二種方式比第一種方式繁瑣,但是效果會更好一些。
H. LINUX 終端設備驅動
在Linux系統中,終端是一種字元型設備,它有多種類型,通常使用tty (Teletype)來簡稱各種類型的終端設備。對於嵌入式系統而言,最普遍採用的是UART (Universal Asynchronous Receiver/Transmitter)串列埠,日常生活中簡稱串口。
Linux內核中tty的層次結構它包含tty核心tty_10.c、tty或路規在n_tty.C(頭現N_11Y線路規程)和tty驅動實例xxx_tty.c,tty線路規程的工作是以特殊的方式格式化從一個用戶或者硬體收到的數據,這種格式化常常採用一個協議轉換的形式tty _io.c本身是一個標準的字元設備驅動,它對上有字元改備的職貢,買現tle_operatIonS雙貝圖效。但是tty核心層對下又定義了tty_driver的架構,這樣tty設備驅動的主體工作就變成了琪允tty_driVeT依構體中的成員,實現其中的tty_operations的成員函數,而不再是去實現file_operations這一級的工作。tty設備發送數據的流程為:tty核心從一個用戶獲取將要發送給一個tty設備的數據,tty核心將數據傳遞給tty線路規程驅動,接著數據被傳遞到tty驅動,tty驅動將數據轉換為可以發送給硬體的格式。接收數據的流程為:從tty硬體接收到的數據向上交給tty驅動,接著進入tty線路規程驅動,再進入tty核心,在這里它被一個用戶獲取。盡管一個特定的底層UART設備驅動完全可以遵循上述tty_driver的方法來設計,即定義tty_driver並實現tty_operations中的成員函數,但是鑒於串口之間的共性,Linux考慮在文件drivers'ttyliserial'serial_core.c中實現了UART設備的通用tty驅動層(我們可以稱其為串口核心層)。這樣,UART驅動的主要任務就進一步演變成了實現serial-core.c中定義的一組uart_xxx介面而不是tty_xxx介面。因此,按照面向對象的思想,可以認為tty_driver是字元設備的泛化、serial-core是tty_driver的泛化,而具體的串口驅動又是serial-core的泛化。