應用負載均衡之LVS(二):VS_TUN和VS_DR的arp問題

来源:https://www.cnblogs.com/f-ck-need-u/archive/2018/02/20/8455004.html
-Advertisement-
Play Games

本文目錄:1. ARP協議簡介2. arp_ignore和arp_announce變數的作用分析 2.1 arp_ignore 2.2 arp_announce3. 設置arp_ignore和arp-announce 1. ARP協議簡介 ARP(Address Resolution Protoco ...


本文目錄:
1. ARP協議簡介
2. arp_ignore和arp_announce變數的作用分析
 2.1 arp_ignore
 2.2 arp_announce
3. 設置arp_ignore和arp-announce

1. ARP協議簡介

ARP(Address Resolution Protocol)協議稱為地址解析協議,用於將主機IP地址解析為主機的MAC地址,即IP<-->MAC之間一一映射。RARP協議相反,是將MAC地址解析為IP地址。

ARP解析時分兩種情況:

  1. 解析目標和自己在同一網段。
    A解析同網段的B,A根據自己的IP和子網掩碼判斷B和自己同網段,這時A就直接在這個網段上發一個ARP廣播包尋求B的MAC地址,所有人都收到廣播信息,但是B會將MAC地址回應給A,A緩存B的MAC地址。
  2. 解析目標和自己不在同一網段。
    A根據自己的IP和子網掩碼判斷出B和自己不在同一個網段,這時A就向自己的網段發送一個ARP廣播包用來解析網關的MAC地址,也就是路由器的介面MAC地址,然後路由器回應,A緩存回應的MAC結果。

當發送ARP請求廣播後,目標設備會進行應答,其中請求數據包和應答數據包的格式非常接近。以下是請求包和應答包數據格式的部分,完整格式請百度或者翻閱TCP/IP協議捲(一)。

其中:

  • op欄位是一個1-4的值,1表示該數據幀是ARP請求包,2表示該數據幀是ARP應答包,3和4則表示RARP的請求和應答包。
  • src_MAC和src_IP是數據幀中的源MAC和源IP地址。這兩個欄位的值不一定是對應的,意思是src_IP不一定配置在src_MAC地址的介面上。
  • dest_MAC和dest_IP則是目標MAC地址和目標IP地址。對於ARP請求包,dest_MAC值為"ff:ff:ff:ff:ff:ff",表示這是廣播包。同樣,這兩個欄位的值也並非是對應的。

當發送ARP請求廣播包時,op的值設置為1,目標MAC設置為廣播地址"ff:ff:ff:ff:ff:ff",然後在區域網內廣播,這是在詢問"who has DEST_IP"。每台主機都能收到該廣播包,但只有設置了目標IP的主機才會應答:"Reply DEST_IP is-at DEST_MAC"。應答時使用單播包進行回應,會將op值改為2,表示這是應答包,同時將應答的MAC地址替換原來的"ff:ff:ff:ff:ff:ff",並將src和dest的欄位位置進行調換。如下圖:

當響應者接收到請求者的ARP請求時,它會將請求包中的源MAC和源IP緩存到ARP緩存表中。當請求者接收到響應者的應答包時,它會將應答包中的源MAC地址和源IP地址緩存到ARP緩存表中。也就是說,一次arp請求,會讓兩端主機都緩存對方的IP和MAC地址。

使用ping命令或其他TCP連接時,兩端都會緩存對方的ARP條目。但為了測試,可以手動使用arping命令發送一個自定義源MAC和源IP的arp請求讓對方緩存自己的IP和MAC。

假如主機A上有eth0(192.168.100.54)和eth1兩網卡,主機B有eth0(192.168.100.70)。下麵的命令表示,在主機A上向主機B發送一個arp廣播包(如果"-c N"的N大於1,則只有第一個請求包是廣播,其他是單播),其中源MAC為eth1網卡的MAC,但源IP為eth0上的IP地址192.168.100.54。這會使得主機B緩存的arp條目為192.168.100.54<-->eth1_MAC,但實際上這並非正確的映射關係。

arping -c 1 -I eth1 src 192.168.100.54 192.168.100.70

有些程式可以檢測到IP地址衝突的現象。典型的如DHCP伺服器準備提供IP地址給客戶端之前,會發送一個arp廣播,以便確認該IP地址是否已被其他主機使用(例如其他主機使用靜態IP時手動輸入了該IP)。如果沒有收到回應,則表示該IP地址沒有被使用,可以提供給客戶端使用,如果收到了回應,則表示該IP地址已經被使用了,DHCP會從IP池中換一個IP提供給客戶端。

arp -a命令可以顯示arp緩存表的內容,arp -d ADDR可以刪除ARP緩存表中某條ARP記錄,這兩命令對於Windows和Linux系統都可用。此外,對於Windows,arp -d *表示刪除arp緩存表中的所有記錄,對於Linux,則使用ip neigh flush all命令來刪除arp緩存中所有記錄。

註意,無論是arp請求還是arp應答,都帶有完整的源MAC、源IP、目標MAC和目標IP。這看似一句廢話,但不熟知arp請求的人很容易因此而陷入困惑。

2. arp_ignore和arp_announce變數的作用分析

在設置VS/TUN和VS/DR時,需要設置到這兩個arp相關的內核變數,所以這裡先解釋解釋。

前文已經說明瞭arp請求包或應答包中,MAC地址可以和IP地址不對應。這樣一來就出現問題了,ARP請求包中,使用哪個源IP地址以及哪個源MAC地址?ARP應答包中,使用哪個源MAC和源IP地址(註意,應答包中源IP地址並不一定是請求包中的目標IP,可能會更換為本機的其他IP地址)?

arp_ignore和arp_announce這兩個變數的作用正是設置使用哪個源IP和哪個源MAC。其中arp_ignore設置的是收到請求包後,在應答包中將本機的哪個IP地址和MAC地址回應給請求者以供緩存;arp_announce設置的是發出請求包時,選擇哪個IP和MAC地址供響應者緩存,這也符合announce的字面意思:向外通告本機的哪個IP地址和MAC地址供其他主機緩存。

它們的作用如下圖所示:

再來細看arp_ignore和arp_announce的介紹。

2.1 arp_ignore

arp_ignore - INTEGER
    Define different modes for sending replies in response to
    received ARP requests that resolve local target IP addresses:
    0 - (default): reply for any local target IP address, configured
    on any interface
    1 - reply only if the target IP address is local address
    configured on the incoming interface
    2 - reply only if the target IP address is local address
    configured on the incoming interface and both with the
    sender's IP address are part from same subnet on this interface
    3 - do not reply for local addresses configured with scope host,
    only resolutions for global and link addresses are replied
    4-7 - reserved
    8 - do not reply for all local addresses

    The max value from conf/{all,interface}/arp_ignore is used
    when ARP request is received on the {interface}

大致翻譯一下:

該變數接受一個整數值。定義的是當本機接收到別的主機發送的ARP請求時的不同應答模式:回應哪個IP和MAC地址給請求者。

  • 0 - (default):將本機所有非lo介面的IP地址都回應出去。
  • 1 - 只有當ARP請求中的目標IP地址配置在流入介面上時才響應。
  • 2 - 只有當ARP請求中的目標IP地址配置在流入介面上時,且該IP地址是介面地址上的子網地址時才響應(例如192.168.100.10/24和192.168.100.10/16的關係)。
  • 3 - do not reply for local addresses configured with scope host, only resolutions for global and link addresses are replied。
  • 4-7 - 保留
  • 8 - 不回應任意地址。
  • 當某介面接收到ARP請求時,

舉個例子來解釋值為0和1的情況。

(1)arp_ignore=0時,當主機收到arp請求時,會將本機任意可能的IP地址都應答給arp請求者。

例如,主機A有3個網卡,eth0(192.168.100.17/24),eth1(192.168.100.36/24)和eth2(172.16.10.10/16),主機B有網卡eth0(192.168.100.39)。當主機B發起對192.168.100.36或17的ping時,由於主機A回應icmp響應給主機B時,預設情況下有以下路由:

[root@xuexi ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.2   0.0.0.0         UG    100    0        0 eth0
0.0.0.0         192.168.100.2   0.0.0.0         UG    101    0        0 eth1
0.0.0.0         192.168.100.2   0.0.0.0         UG    102    0        0 eth2
172.16.0.0      0.0.0.0         255.255.0.0     U     100    0        0 eth2
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     101    0        0 eth1
192.168.100.2   0.0.0.0         255.255.255.255 UH    100    0        0 eth2

這時主機A會將eth0和eth1上的IP地址都應答給主機B,且這兩個IP地址對應的MAC地址都是eth0(因為該介面是該網段的第一條路由出口)的MAC地址。以下是主機B上ping 192.168.100.36後的arp緩存表,如果結果不同,請ip neigh flush all清空緩存表或者多等待一段時間再測試。

[root@xuexi ~]# ip n s 
192.168.100.36 dev eth0 lladdr 00:0c:29:fb:dd:04 REACHABLE
192.168.100.1 dev eth0 lladdr 00:50:56:c0:00:08 REACHABLE
192.168.100.17 dev eth0 lladdr 00:0c:29:fb:dd:04 STALE

如果將主機A上192.168.100.0 eth0的路由條目刪除,則主機B ping 192.168.100.36時,主機A將不再把eth0(192.168.100.17)響應給主機B,儘管它可以使用eth1對應的路由出去。但如果主機B ping 192.168.100.17,那麼也會將該地址響應出去,使用的源MAC地址也是eth1(因為路由出口為eth1)。因此,主機B只會緩存主機A的192.168.100.36 eth1_MAC。

由此可知,所謂響應任意可能的IP地址並不是響應所有地址,lo介面、非同一網段地址以及無第一路由的介面地址就不會主動響應出去。同樣,那些定義在介面上的別名地址也預設不會響應出去,因為它們的數據的流入流出都是通過它所依附的介面。

(2)arp_ignore=1時,當主機收到arp請求時,只有arp請求包中目標IP和流入介面上的IP相同時,才會響應該IP以及該介面的MAC。

例如,設置eth0網卡的該變數值為1。不過,為了完善測試,先將上面示例中刪除的路由條目添加回來。

route add -net 192.168.100.0/24 dev eth0

echo 1 >/proc/sys/net/ipv4/conf/eth0/arp_ignore

這時主機B上ping 192.168.100.17時,主機A將只會響應eth0_MAC給主機B,且ping 192.168.100.36時將ping不通(這一點需要註意,在後面配置LVS的arp參數時,外界主機往往只能ping通同網段的其中一個地址)。以下是在主機B上ping 192.168.100.36時在主機A上抓取的數據包。

[root@xuexi ~]# tcpdump -nn host 192.168.100.39
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:21:51.739967 ARP, Request who-has 192.168.100.36 tell 192.168.100.39, length 46
12:21:52.739741 ARP, Request who-has 192.168.100.36 tell 192.168.100.39, length 46
12:21:53.739868 ARP, Request who-has 192.168.100.36 tell 192.168.100.39, length 46
12:21:55.742680 ARP, Request who-has 192.168.100.36 tell 192.168.100.39, length 46
12:21:56.743560 ARP, Request who-has 192.168.100.36 tell 192.168.100.39, length 46
12:21:57.743086 ARP, Request who-has 192.168.100.36 tell 192.168.100.39, length 46
^C
6 packets captured
6 packets received by filter
0 packets dropped by kernel

從結果中可以看出,主機A收到目標IP為192.168.100.36的ARP請求後,完全沒有對其給出響應動作。因為主機B發出的ARP請求包到達主機A時的流入介面為eth0,而192.168.100.36並不是配置在eth0上,由於eth0的arp_ignore=1,所以不會應答對192.168.100.36的arp請求,主機B也就不知道192.168.100.36的MAC地址,從而無法與A主機通信。

這裡的關鍵是主機A上ARP請求的流入介面是eth0而不是eth1,儘管ping的目標是eth1:192.168.100.36。也就是說,只要eth0的arp_ignore=1,那麼該主機上該網段的所有地址(除了配置在eth0上的IP)都無法與外界通信。

之所以主機A上請求的流入介面是eth0而非eth1(此處eth0和eth1同網段),這是主機A的路由表決定的。因此在arp請求過程中,路由表中路由的先後順序非常重要,它不僅決定了數據從哪流入流出,還決定了流入、流出時使用哪個MAC地址,而這直接決定是否能成功ARP請求、ARP響應以及arp緩存的IP<-->MAC映射結果。如果你在學習arp_ignore和arp_announce時做了很多測試,必然能體會到這一點。

2.2 arp_announce

arp_announce - INTEGER
    Define different restriction levels for announcing the local
    source IP address from IP packets in ARP requests sent on
    interface:
    0 - (default) Use any local address, configured on any interface
    1 - Try to avoid local addresses that are not in the target's
    subnet for this interface. This mode is useful when target
    hosts reachable via this interface require the source IP
    address in ARP requests to be part of their logical network
    configured on the receiving interface. When we generate the
    request we will check all our subnets that include the
    target IP and will preserve the source address if it is from
    such subnet. If there is no such subnet we select source
    address according to the rules for level 2.
    2 - Always use the best local address for this target.
    In this mode we ignore the source address in the IP packet
    and try to select local address that we prefer for talks with
    the target host. Such local address is selected by looking
    for primary IP addresses on all our subnets on the outgoing
    interface that include the target IP address. If no suitable
    local address is found we select the first local address
    we have on the outgoing interface or on all other interfaces,
    with the hope we will receive reply for our request and
    even sometimes no matter the source IP address we announce.

    The max value from conf/{all,interface}/arp_announce is used.

    Increasing the restriction level gives more chance for
    receiving answer from the resolved target while decreasing
    the level announces more valid sender's information.

大致翻譯一下:該變數接受一個整數值。它定義的是當發送ARP請求時,在請求數據包中填入的源IP地址和源MAC地址,它們是被響應者緩存的內容

  • 0 - (default)可以使用本機上任意介面的任意地址。
  • 1 - 儘量不使用不在目標IP所在子網的地址。當目標主機可以通過該介面達到,但要求ARP數據包中的源IP地址是邏輯網路介面網段中的地址時,設置為該級別很有用。當生成ARP請求數據包時,將檢測所有包含目標IP的子網(自身網段或子網都可以),如果源IP地址處於該子網內,則使用該地址。如果沒有包含該源IP地址的子網,則使用級別2(arp_announce=2)來處理。

  • 2 - 總是為目標地址尋找最佳本地地址作為ARP請求的源IP地址。這種模式下,將忽略源IP地址,而是嘗試選擇出能和目標IP最佳通信質量的IP地址。這個IP是通過尋找各流出介面上的主IP地址(primary IP,不能是secondary IP)得到的,它需要和目標IP地址在同網段或屬於其子網內。如果沒有選出合適的地址,將選擇第一個流出介面上的IP地址,這樣不僅可以接收到應答包,還能無視已經手動通告的源地址。

稍微解釋下。

  • arp_announce=0時,向外發送ARP請求時,很可能會使用流出介面的IP地址和MAC地址,這沒有硬性限制。
  • arp_announce=1時,儘量使用與目標IP地址在同一子網的地址,例如目標IP地址為192.168.100.40/16,而本機有IP地址192.168.100.22/24,這個IP地址是目標IP地址子網內的一個地址,因此會儘量使用該地址作為ARP請求中的源IP地址,但是源MAC地址還是數據流出介面上的MAC。
  • arp_announce=1時,不管ARP請求包中指定的源IP地址是什麼(因為ARP請求包中的源IP和源MAC可以手動指定),總會在本地搜索出和目標IP最匹配的IP地址來作為源地址。它會優先選和目標IP同子網的本地IP,如果沒有則選路由表中的第一個流出介面上的IP。

例如,如果Linux主機有3個網卡:eth0(IP0)、eth1(IP1)和eth2(IP2)。如果想通過eth2介面流出源地址為IP0的ARP請求廣播包,預設情況下是行不通的。因為預設情況下,使用eth2流出ARP請求的源IP地址必須使用IP2。因此必須設置arp_announce=1或2,其實設置為1時也只是有機會流出,因為它要判斷IP0和目標IP地址是否存在子網所屬關係。只有設置arp_announce=2才必然能流出,但這時該Linux主機向外通告的IP地址將不是IP0,而是IP2。

3.設置arp_ignore和arp_announce

Linux內核2.0.xx版本中,迴環介面、迴環別名介面(如lo:0,lo:1)以及迴環隧道介面都不會做arp回應,對於LVS集群來說,這很方便。但從Linux 2.2.xx開始,除了迴環地址(127.0.0.0/8)和廣播地址外,其他所有地址(包括迴環介面上的別名介面)都會做arp回應。因此,在這樣的內核版本下配置LVS可能會出現一些問題。從Linux內核2.2.14開始,提供了一個介面標記"hidden"用於從ARP廣播中隱藏指定介面

這意味著對於現在的CentOS6、CentOS7來說,雖然每個介面(包括lo介面)都可以設置這兩個變數,但這兩個變數只對能arp回應的介面才生效(如eth0,eth1等對外通信的普通介面)。也就是說,在lo介面上設置arp_ignore、arp_announce等arp參數是沒有意義的

儘管對lo介面設置arp參數沒有意義,但為了保證lo和普通網卡、隧道設置方法的統一性,以及未來的內核可能對此做出改變,本文以及網上的文章還是對它進行了同樣的設置。

例如,設置lo介面的arp_ignore=1、arp_announce=2。

echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce

如果在介面上設置了別名IP,例如eth0:0,由於它們仍然使用所依附的介面流入流出數據,因此在介面上設置arp_ignore和arp_announce對別名IP同樣生效。

其實,在/proc/sys/net/ipv4/conf下,除了各網卡介面的配置目錄,還有default和all兩個目錄,這兩個目錄內關於arp參數的值隻影響普通網卡,不影響lo介面,也沒有意義去影響lo介面。

[root@xuexi ~]# ls -l /proc/sys/net/ipv4/conf/
total 0
dr-xr-xr-x 1 root root 0 Feb 15  2018 all
dr-xr-xr-x 1 root root 0 Feb 15  2018 default
dr-xr-xr-x 1 root root 0 Feb 14 22:56 eth0
dr-xr-xr-x 1 root root 0 Feb 14 22:56 eth1
dr-xr-xr-x 1 root root 0 Feb 14 22:56 lo

其中:

  • default目錄中的變數值為普通網路介面提供初始化值(不影響lo介面)。這個目錄其實沒什麼用,因為每次重啟操作系統,/proc/sys下的設置都會失效,而直接設置該目錄下的值又起不到提供初始化值的作用。之所以放在conf目錄內是為了提示我們可以設置default屬性的值。例如,向sysctl.conf中追加永久設置net.ipv4.conf.default.arp_ignore=1,這樣每次重啟系統後各網卡介面的arp_ignore級別都是1(註意:普通網卡才生效,lo介面不受影響)。
  • all目錄中的變數作用範圍是所有網卡(不包括lo介面)。

對於每個網卡來說,將比較all目錄中的變數值和網卡自身的變數值,取較大值。例如:

conf/eth0/arp_ignore值為1,conf/all/arp_ignore值為0,則對於eth0介面來說,arp_ignore=1。
conf/lo/arp_announce值為0,conf/all/arp_announce值為2,則對於lo介面來說,arp_announce=0,因為all目錄不影響lo介面。但最終,lo介面上設置的arp參數值是沒有意義的。

通常,VS/TUN和VS/DR模式下,Real Server上的VIP設置在lo的別名介面上(如lo:0上),因此應該如下設置:

echo 1 >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo 1 >/proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 >/proc/sys/net/ipv4/conf/lo/arp_announce
echo 2 >/proc/sys/net/ipv4/conf/all/arp_announce

其中生效的為第二條和第四條規則,第一條和第三條對lo介面的設置語句可有可無。

將conf/all/arp_ignore設置為1,可以保證無論哪個對外通信的網卡介面都只會向外響應自己介面上的IP地址(甚至可能有些同網段的介面因為路由順序排在後面而響應不出去),這樣就隱藏了設置在lo別名介面上的VIP地址。
將conf/all/arp_announce設置為2,可以保證本機只向外通告普通網卡上的IP地址,lo別名介面上的VIP不可能被通告出去。

 

回到Linux系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
回到網站架構系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
回到資料庫系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7586194.html
轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/8455004.html

註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、冒泡排序 a、冒泡排序 優化 如果冒泡排序中執行一趟而沒有交換,則列表已經是有序狀態,可以直接結演算法 二、選擇排序 a、一趟遍歷記錄最小的數,放到第一個位置; b、在一趟遍歷記錄剩餘列表中最小的數,繼續放置 三、插入排序 a、列表被分為有序區和無序區兩個部分,最初有序區只有一個元素 b、每次從無 ...
  • 本系列上一篇文章中我們就說到了,這一次我們要說 pop3 收信了。雖然我覺得應該先說完 mime 格式,不過估計大家已經不耐煩了 -- 怎麼老在說發送啊?我們要看收取! 好吧,來啦,來啦!收取郵件現在常用的有 pop3 和 imap 協議,不過從傳統來說 pop3 受眾要廣得多。有了前面的基礎,要實 ...
  • 使用opencv-python一段時間了,因為之前沒有大量接觸過c++下的opencv,在網上看c++的一些程式想改成python遇到了不少坑,正好在這裡總結一下。 1.opencv 中x,y,height, width,rows,cols 的關係(轉自http://blog.csdn.net/ik ...
  • abs(x) 求一個數的絕對值。 all(iterable) 如果迭代器中的所有值都為“真”則返回 True, 否則返回 False 註意: 如果迭代器為空,返回 True any(iterable) 如果迭代器中的任意一個值為“真”則返回 True, 否則返回 False 註意: 如果迭代器為空, ...
  • 格式化代碼: ^I 轉到定義:⌘D 註釋/反註釋: ⌘/ 生成:⌘B 重新生成:^⌘B 調試運行:⌘↩ 不調試運行:⌥⌘↩ 添加/刪除斷點:⌘\ 查看所有斷點:⌥⌘↩ 放大:⌘+ 縮小:⌘- 正常大小:⌘0 全屏/取消全屏:^⌘F 頁內搜索:⌘F 文件/項目內搜索:⇧⌘F 上一步操作游標:⌃⌘← 下 ...
  • 記錄了從查找Windows Live Writer上VSPasste插件丟失RTF格式信息問題的原因,到最終解決問題的整個經歷。 ...
  • 微軟在06月27日發佈了Visual Studio 2015 Update 3 。在MSDN中微軟也提供下載,而且MSDN的Visual Studio 2015 Update 3與官方免費下載的文件是一致的,只是文件名不一樣,除TFS除外。官方下載:https://www.visualstudio. ...
  • 一、背景 春節也不能閑著,一直想學一下爬蟲怎麼玩,網上搜了一大堆,大多都是Python的,大家也比較活躍,文章也比較多,找了一圈,發現園子裡面有個大神開發了一個DotNetSpider的開源庫,很值得慶幸的,該庫也支持.Net Core,於是乘著春節的空檔研究一下整個開源項目,順便實戰一下。目前互聯 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...