Varnish的VCL

来源:https://www.cnblogs.com/shenxm/archive/2018/02/24/8465135.html
-Advertisement-
Play Games

Varnish的子進程 VCL varnish的有限狀態機 客戶端和後端工作線程的詳細的varnish請求流程 VCL語法 VCL函數、關鍵字和變數 ...


Varnish的子進程

VCL

    Varnish配置語言VCL是一種“域”專有類型的配置語言,用於描述Varnish Cache的請求處理和文檔高速緩存策略。
    當載入新配置時,Manager進程會創建VCC進程,然後將VCL代碼轉換為C代碼,C代碼被gcc編譯成共用對象,然後共用對象被載入到cacher進程中。
    VCL有多個狀態引擎(state engine),狀態之間存在相關性,但狀態引擎彼此間互相隔離。
    每個狀態引擎可使用return(x)指明關聯至哪個下一級引擎,每個狀態引擎對應於vcl文件中的一個配置段,即為subroutine。
        vcl_hash --> return(hit) --> vcl_hit

varnish的有限狀態機

    實際上     
        vcl_recv ——>vcl_purge/vcl_pipe/vcl_hash     
        vcl_hash——>vcl_miss/vcl_hit     
        其他的如圖所示     
        vcl_hash --> return(X) --> vcl_X        
                
    VCL工作流看作是一個有限狀態機 。
    每個請求被分開處理,每個請求在任何給定的時間都是獨立於其他人的,狀態是相關的但也是孤立的。
    內置的VCL代碼始終存在,並附加在您自己的VCL下麵。
    當Varnish處理請求時,它首先解析請求本身,稍後Varnish將請求方法從頭文件中分離出來,驗證它是否是有效的HTTP請求等等。
    當基本解析完成後,首先檢查策略以作出決定,策略是VCL代碼用於做出決定的一組規則。
    每個狀態都在VCL編碼中有對應的可用參數,在VCL上的狀態被概念化為子進程,在VCL中採用的等待狀態描述中的等待狀態即不是參數也不是返回值。
    每個內置的子程式以首碼vcl_開始,被return(action)終止,退出當前狀態並指示varnish進入下一個狀態,其中action是一個關鍵詞用於指定期望的輸出。
    子進程可以檢查和操控http報文頭部區域和各種其他方面的請求,並指示如何處理請求。
    varnish創建的子進程被掛在varnish的工作中,這些子進程被以vcl_為首碼來命名的,而我們自己的進程就不能以其為首碼命名。
    我們稱這些有關狀態的子進程為狀態引擎(state engine),VCL有多個狀態引擎,狀態之間存在相關性,但狀態引擎彼此間互相隔離,每個狀態引擎可使用return(x)指明關聯至哪個下一級引擎,每個狀態引擎對應於vcl文件中的一個配置段,即為subroutine。
    vcl_recv的預設配置:
        sub vcl_recv {
            if (req.method == "PRI") {
                /* We do not support SPDY or HTTP/2.0 */
                return (synth(405));
            }
            if (req.method != "GET" &&
            req.method != "HEAD" &&
            req.method != "PUT" &&
            req.method != "POST" &&
            req.method != "TRACE" &&
            req.method != "OPTIONS" &&
            req.method != "DELETE") {
                /* Non-RFC2616 or CONNECT which is weird. */
                return (pipe);
            }
    
            if (req.method != "GET" && req.method != "HEAD") {
                /* We only deal with GET and HEAD by default */
                return (pass);
            }
            if (req.http.Authorization || req.http.Cookie) {
                /* Not cacheable by default */
                return (pass);
            }
                return (hash);
            }
        }

客戶端和後端工作線程的詳細的varnish請求流程

    Client Side:
        vcl_recv, vcl_pass, vcl_hit, vcl_miss, vcl_pipe, vcl_purge, vcl_synth, vcl_deliver
    Backend Side:
        vcl_backend_fetch, vcl_backend_response, vcl_backend_error
    vcl_recv:
        hash:vcl_hash
        pass: vcl_pass 
        pipe: vcl_pipe
        synth: vcl_synth
        purge: vcl_hash --> vcl_purge
    vcl_hash:
        lookup:
        hit: vcl_hit
        miss: vcl_miss
        pass, hit_for_pass: vcl_pass
        purge: vcl_purge
    兩個特殊的引擎:
        vcl_init:在處理任何請求之前要執行的vcl代碼:主要用於初始化VMODs;
        vcl_fini:所有的請求都已經結束,在vcl配置被丟棄時調用;主要用於清理VMODs;

VCL語法

        VCL文件以vcl 4.0開始;
        //,#和/ *  * /是註釋
        子進程用sub關鍵字聲明
        沒有迴圈,狀態有限的變數
        用下一個關鍵字作為return()函數的參數來終止語句,即:return(action)
        特定領域
    從Varnish 4.0開始,每個VCL文件必須首先在文件頂部用一個特殊的標記聲明它的版本。
    塊由花括弧分隔,以分號結尾。
    VCL中的子程式既不帶參數,也不返回值。
    VCL中的子程式只能通過HTTP頭交換數據。
    VCL有終止語句,而不是傳統的返回值。
    子程式在執行return(*action*)語句時結束執行。
    該行action告訴varnish下一步該做什麼。
    VCL有兩個指令來使用來自另一個文件的內容,這些指令是include和import,並用於不同的目的。
        include用於從另一個文件插入VCL代碼,Varnish查找被varnishd的vcl_dir參數指定目錄中的文件,請註意include語法中的引號。
        import用於載入VMOD並將其功能提供給VCL代碼,Varnish將查找VMOD以載入到由varnishd的vmod_dir參數指定的目錄。
        請註意import語法中缺少引號,你可以使用varnishtest中的include和import。
    三類主要語法:
        sub subroutine {
            ...
        }
        
        if CONDITION {
            ...
        } else {    
            ...
        }
        
        return(), hash_data()

VCL函數、關鍵字和變數

    函數:
        regsub(str, regex, sub)
        regsuball(str, regex, sub)
        ban(boolean expression)
        hash_data(input)
        synthetic(str)
    Keywords:
        call subroutine
        return(action)
        new
        set
        unset 
    操作符:
        ==, !=, ~, >, >=, <, <=
        邏輯操作符:&&, ||, !
        變數賦值:=
    舉例:
        obj.hits是內建變數,用於保存某緩存項的從緩存中命中的次數;
        if (obj.hits>0) {
            set resp.http.X-Cache = "HIT via " + server.ip;
                } else {
                    set resp.http.X-Cache = "MISS from " + server.ip;
                }
    
    變數類型:
        內建變數:
            req.*:request,表示由客戶端發來的請求報文相關;
                req.http.*
                    req.http.User-Agent, req.http.Referer, ...
            bereq.*:由varnish發往BE主機的httpd請求相關;
                bereq.http.*
            beresp.*:由BE主機響應給varnish的響應報文相關;
                beresp.http.*
            resp.*:由varnish響應給client相關;
            obj.*:存儲在緩存空間中的緩存對象的屬性;只讀;
            
        常用變數:
            bereq.*, req.*:
                bereq.http.HEADERS
                bereq.request:請求方法;
                bereq.url:請求的url;
                bereq.proto:請求的協議版本;
                bereq.backend:指明要調用的後端主機;
                req.http.Cookie:客戶端的請求報文中Cookie首部的值; 
                req.http.User-Agent ~ "chrome"
            beresp.*, resp.*:
                beresp.http.HEADERS
                beresp.status:響應的狀態碼;
                reresp.proto:協議版本;
                beresp.backend.name:BE主機的主機名;
                beresp.ttl:BE主機響應的內容的餘下的可緩存時長;
            obj.*
                obj.hits:此對象從緩存中命中的次數;
                obj.ttl:對象的ttl值
            server.*
                server.ip:varnish主機的IP;
                server.hostname:varnish主機的Hostname;
            client.*
                client.ip:發請求至varnish主機的客戶端IP;
            
        用戶自定義:
            set 
            unset 

    vcl_backend_response
            覆蓋某些URL的緩存時間
            剝離Set-Cookie不需要的頭部欄位
            剝離Vary頭部欄位
            將helper-headers添加到對象以用於禁止
            清理伺服器響應
            應用其他緩存策略
        vcl_backend_response採用以下其中之一會被終止:deliver,retry,abandon。
        deliver終止動作可以或者可以不依賴於後端的響應插入對象到緩存中。
        retry操作使Varnish通過調用vcl_backend_fetch子程式再次將請求傳輸到後端。
        abandon操作會放棄來自後端的任何響應。
        後端可能會響應一個304HTTP頭部,當有時間戳if-modified-since在http頭部,且請求對象沒能被修改時304響應會發生。
        如果請求觸及一個非新鮮的對象,Varnish將If-Modified-Since頭的值添加t_origin到請求中,並將其發送到後端。
        304響應不包含消息正文,因此Varnish使用緩存中的實體構建響應,304響應更新緩存對象的屬性。
        內建vcl_backend_response
            sub vcl_backend_response {
                if (beresp.ttl <= 0s ||
                    beresp.http.Set-Cookie ||
                    beresp.http.Surrogate-control ~ "no-store" ||
                    (!beresp.http.Surrogate-Control &&
                    beresp.http.Cache-Control ~ "no-cache|no-store|private") ||
                    beresp.http.Vary == "*") {
                    /*
                     * Mark as "Hit-For-Pass" for the next 2 minutes
                     */
                    set beresp.ttl = 120s;
                    set beresp.uncacheable = true;
                }
                return (deliver);
            }
            vcl_backend_response內建子進程被設計於避免緩存那些不希望的情況。
            例如,避免緩存cookies響應,帶有set-cookie http頭域的響應,這個內建子進程也避免請求serialization,這個在waiting state選項中有描述。
            為避免請求serialization,beresp.uncacheable被設定為true,並輪流創建以hit-fot-pass對象。
            hti-fot-pass詳細解釋了這個對象的類型。
            如果你仍然決定通過採用自己設定的來跳過內建vcl_backend_response子進程,請確保絕不要設定beresp.ttl為0。
            如果你跳過內建子進程並設置TLL值為0,可以有效地從緩存中刪除最終有可能用於避免請求serialization的對象。
            berep.ttl的初始值
                在varnish運行vcl_backend_response前,beresp.ttl變數就已經被設定了。
                beresp.ttl用它在下麵找到的第一個值進行初始化:
                    Cache-Control響應頭欄位中的s-maxage變數
                    Cache-Control響應頭欄位中的max-age變數
                    Expires響應報頭欄位
                    default_ttl參數
                預設情況,下麵的狀態碼會被緩存:
                    200:ok
                    203:非權威信息
                    300:多種選擇
                    301:永久移動
                    302:暫時移動
                    304:沒有修改
                    307:臨時重定向
                    410:gone
                    404: Not Found
                你可以不採用上面列出的而緩存其他狀態碼,但你需要在vcl_backend_response中給beresp.ttl設置一個正值。
                因為beresp.ttl的設置是在vcl_backend_response執行之前,你可以修改cache-control頭域的導引而不英雄beresp.ttl,反之亦然。
                後端響應可能包括共用緩存s-maxage的最大響應頭欄位,通過所有varnish服務該欄位覆蓋了所有max-age值。
                例如,如果後端發送cache-control:max-age=300,s-maxage=3600,所有varnish installations將緩存帶有一個age值大於等於3600秒的緩存對象,這就意味著在age為301到3600s間的響應將不會被客戶端web瀏覽器緩存,這是因為age的值超過了max-age。
                一個明智的方法是使用s-maxage指令來指示varnish緩存響應。然後,在遞送響應前使用vcl_backend_response上的regsub()來刪除s-maxage指定。採用這個方法,你可以為varnish servers安全地使用s-maxage,併為客戶端設置max-age為持續緩存。
                警告 :
                    請記住,刪除或更改Age響應標題欄位可能會影響響應在下游的處理方式。刪除Age欄位的影響取決於下游中間件或客戶端的HTTP實施。例如,假設您有三個varnish伺服器串列設置。如果您刪除Age第一個Varnish伺服器中的欄位,則第二個Varnish伺服器將假定Age=0。在這種情況下,您可能會無意中將陳舊的對象傳遞給客戶端。
            示例:
                1.設置.jpg urls的TTL設置為60秒
                    sub vcl_backend_response {
                        if (bereq.url ~ "\.jpg$") {
                            set beresp.ttl = 60s;
                        }
                    }
                    上面的例子將以.jpg結尾的所有URL緩存60秒。請記住,內置的VCL仍然被執行。這意味著帶有Set-Cookie欄位的圖像不會被緩存。
                2.緩存.JPG 60秒僅當s-maxage不存在
                    sub vcl_backend_response {
                        if (beresp.http.cache-control !~ "s-maxage" && bereq.url ~ "\.jpg$") {
                            set beresp.ttl = 60s;
                        }
                    }

VCL子程式

    VCL子進程,在其中定製Varnish的行為。
    VCL子常式可用於:
        添加自定義標頭,更改Varnish錯誤消息的外觀,在Varnish中添加HTTP重定向功能,清除內容以及定義緩存對象的哪些部分是唯一的。
    註意 
        強烈建議儘可能讓預設的內置子程式,內置子程式的設計考慮到安全性,這通常意味著它們可以合理的方式處理VCL代碼中的任何缺陷。
    vcl_recv
            規範化客戶端輸入
            選擇一個後端Web伺服器
            重新編寫Web應用程式的客戶端數據
            根據客戶端輸入決定緩存策略
            訪問控制列表(ACL)
            安全屏障,例如針對SQL註入攻擊
            修複錯誤,例如index.htlm- >index.html
        vcl_recv是Varnish第一個VCL子進程,將客戶端請求解析為其基本數據結構之後執行。 
        vcl_recv有四個主要用途:
            修改客戶端數據以減少緩存的多樣性。
            決定使用哪個Web伺服器。
            根據客戶端數據決定緩存策略。
            執行特定Web應用程式所需的重寫規則。
        在vcl_recv你可以執行以下終止操作:
            pass:它通過緩存查找,但它執行Varnish請求流的其餘部分。 pass不會將來自後端的響應存儲在緩存中。
            pipe:此操作創建一個全雙工管道,將客戶端請求轉發到後端,且不查看其內容。後端回覆被轉發回客戶端且不緩存其內容。由於Varnish不再嘗試將內容映射到請求上,因此任何子進程的請求發送給活動連接將被通過pipe轉發。pipe請求不會出現在任何日誌中。
            hash:它在緩存中查找請求。
            purge:它在緩存中查找請求以便刪除它。
            synth -從Varnish生成合成響應。這種合成響應通常是一個帶有錯誤信息的網頁。 synth也可以用來重定向客戶端請求。
        同樣可以使用vcl_recv來設置以下安全措施。varnish不是入侵檢測系統的替代品,但仍可以用來提前阻止一些典型的攻擊。簡單訪問控制列表(ACL)也可以應用到vcl_recv上。
        內建的vcl_recv子進程不會緩存所有你想要的,同時也最好不要緩存錯誤內容而是把它們發送給錯誤的用戶。
        重新訪問內置的vcl_recv:
            sub vcl_recv {
                if (req.method == "PRI") {
                    /* We do not support SPDY or HTTP/2.0 */
                    return (synth(405));
                }
                if (req.method != "GET" &&
                  req.method != "HEAD" &&
                  req.method != "PUT" &&
                  req.method != "POST" &&
                  req.method != "TRACE" &&
                  req.method != "OPTIONS" &&
                  req.method != "DELETE") {
                    /* Non-RFC2616 or CONNECT which is weird. */
                    return (pipe);
                }
                if (req.method != "GET" && req.method != "HEAD") {
                    /* We only deal with GET and HEAD by default */
                    return (pass);
                }
                if (req.http.Authorization || req.http.Cookie) {
                    /* Not cacheable by default */
                    return (pass);
                }
                return (hash);
            }
        例子:
            基本設備檢測
                sub vcl_recv {
                    if (req.http.User-Agent ~ "iPad" ||
                        req.http.User-Agent ~ "iPhone" ||
                        req.http.User-Agent ~ "Android") {
                        set req.http.X-Device = "mobile";
                    } else {
                        set req.http.X-Device = "desktop";
                    }
                }
                
    vcl_pass
        進入pass模式是調用
            sub vcl_pass {
                return (fetch);
            }
        當上一層子進程返回pass動作後才會調用vcl_pass子進程,這動作的請求是在pass模式中設置的,vcl_pass通常作為一個重要的catch-all,服務於vcl_hit和vcl_miss執行結果。
        vcl_pass可能會返回是三個動作:fetch、synth、或者是restart。
        當返回的的是fetch時,正在進行的請求就採用pass模式。
        採用pass模式從請求中抓取的對象不被緩存,但會傳遞到客戶端。
        synth和restart返回的動作會調用相關的子進程。
        hit-for-pass
                當一個對象不應該被緩存是使用
                hit-for-pass對象取代抓取的對象
                存在TTL
            一些請求就不應該被緩存,一個典型的例子就是當一個請求頁中含有set-cookie響應頭部時,且必須並只能把它遞送給所需的客戶端。
            因此你可以告訴varnish創建個hit-for-pass的對象並存儲這個對象到緩存,而不是存儲抓取的這個對象,分散式的請求被採用pass模式處理。
            當一個對象不需要被緩存是,beresp.uncacheable變數會設置為true。
            結果,cacher進程會保持對hit-for-pass對象的hash散列應用,這種情況下,對請求的查找操作會傳遞給hash來找個hit-for-pass對象,如此類的請求會被vclpass子進程中的pass模式給處理。
            如同其他緩存對象一樣,hit-for-pass對象也有一個TTL(生命周期)。一旦生命周期過了,這個對象就會從緩存上刪除。

    vcl_backend_fetch
        sub vcl_backend_fetch {
            return (fetch);
        }
        vcl_backend_fetch 可以從vcl_miss或vcl_pass中調用。當vcl_backend_fetch從vcl_miss中調用時,抓取的對象會被緩存。如果vcl_backend_fetch被從vcl_pass中調用時,抓取的對象也不會被緩存的,即使是obj.ttl或obj.keep變數的值比0大。
        一個相關的變數是bereq.uncacheable,這個變數指示出從後端來的對象請求是否被緩存。當然從pass請求中來的對象是絕不被緩存的。
        vcl_backend_fetch有倆個可能的終端操作,fetch或abandon。fetch動作發送請求給後動,abandon動作調用vcl_synth子進程。內建vcl_bakend_fetch子進程只返回fetch動作。
        後端響應被vcl_backend-response還是vcl_backend_error處理取決於響應來之於那個服務。如果Varnish收到語法正確的HTTP響應,則Varnish將控制權交給vcl_backend_response。語法正確的HTTP響應包括HTTP 5xx錯誤代碼。如果Varnish沒有收到HTTP響應,則將控制權交給vcl_backend_error。
    vcl_hash
            定義什麼是唯一的請求
            vcl_hash終是在vcl_recv後,或者另個子進程範圍hash動作關鍵詞。
            sub vcl_hash {
                hash_data(req.url);
                if (req.http.host) {
                    hash_data(req.http.host);
                } else {
                    hash_data(server.ip);
                }
                return (lookup);
            }
        vcl_hash定義要用於緩存對象的hash key。
        Hash key將一個緩存對象與另一個緩存對象區分開來,預設的VCL為vcl_hash添加主機名或ip地址,同時添加請求的url給cache hash。
        vcl_hash的一個用法是在cache hash上添加用戶名來識別用戶指定的數據,當然緩存用戶數據時應該謹慎進行,一個更好的選擇可能是hash每個會話緩存對象。
        vcl_hash子進程返回lookup操作關鍵字,不像其他動作關鍵詞,lookup是一個操作,而不是子進程,在vcl_hash後的下個狀態取決於在緩存中lookup的查找。
        當lookup操作沒能匹配到任何hash時,它會創建一個帶有busy標誌的對象並存儲在緩存中,然後,請求會被髮送到vcl_miss子進程中,一旦請求被處理busy標誌會被刪除,並從後端的響應中更新對象。
        隨後遇到busy標記的對象請求將被髮送到等待列表中,這個等待名單旨在提高響應性能,這個在waiting state 選項中有解釋。
        註意:一個高速緩存散列可以指代一個或多個對象變數。對象變數是基於Vary頭域的創建的。在一個緩存散列下保留多個變數是比較好的做法,而不是每個變數創建一個散列。
    vcl_hit
            在lookup操作之後執行,調用vcl_hash,找到(hits)在緩存上的對象。
            sub vcl_hit {
                if (obj.ttl >= 0s) {
                    // A pure unadultered hit, deliver it
                    return (deliver);
                }
                if (obj.ttl + obj.grace > 0s) {
                    // Object is in grace, deliver it
                    // Automatically triggers a background fetch
                    return (deliver);
                }
                // fetch & deliver once we get the result
                return (fetch);
            }
        vcl_hit子進程通常通過調用含有deliver,restart或者synth的return()來進行終止。
        如果對象的TTL+grace time沒有過時的話,返回的deliver會控制vcl_deliver。
        如果過時時間超過了TTL,但沒有超過TTL+grace time,deliver會調用與vcl_deliver同步的background fetch。
        background fetch是一種非同步調用,用來插入一個新的請求對象到緩存中。grace time會在grace模式選項中有解釋。
        restart重啟傳輸,並增加重啟計數器設定值。如果重啟的次數比max_restarts設定的值要大,varnish會發出一個guru mediation的錯誤。
        synth(status code,reason)返回指定狀態碼給客戶端並丟棄請求。

    vcl_miss
            如果一個請求對象沒有被lookup操作找到時子進程會被調用。
            包含有是否嘗試從後端檢索文檔以及使用那個後端的策略。
            sub vcl_miss {
                return (fetch);
            }
        子進程vcl_hit和vcl_miss是相關的。你很少調用他們,因為HTTP請求投吧的修改通常是在vcl_recv中進行。但是,如果你不希望發送X-Varnish頭部給後端服務,你可以把它移動動vcl_miss或vcl_pass中。基於這種情況,你可以使用unset bereq ,http,x-varnish。

    vcl_deliver
            所有請求流程的公共最後退出點,除了通過vcl_pipe的請求。
            經常用於添加和移除debug-headers。
            sub vcl_deliver {
                return (deliver);
            }
        vcl_deliver子進程是簡單的,同樣也是對修改varnish的輸出很有用的。如果你需要刪除一個頭部,或添加一個不應該存儲在cache中的頭部,vcl_deliver可以勝任這個工作。
        在vcl_deliver中常用的且被可被修改的變數是:
            resp.http.*:發送個客戶端的頭部,它們可以被set和unset。
            resp.status:狀態碼為200,404,503等
            resp.reason:被返回給客戶端的http狀態信息
            obj.hit:在對象上的cache-hits的數。因此,0代表miss,可以評估這個變數來輕鬆地顯示響應是來自緩存命中還是未命中。
            req.restarts:在VCL中發出的重啟次數 - 如果沒有發生,則返回0。
        
    vcl_synth
            用於在Varnish中生成內容
            錯誤消息可以在這裡創建
            其他用例:重定向用戶(301/302重定向)
            vcl/default-vcl_synth.vcl:
                sub vcl_synth {
                    set resp.http.Content-Type = "text/html; charset=utf-8";
                    set resp.http.Retry-After = "5";
                    synthetic( {"<!DOCTYPE html>
                <html>
                  <head>
                    <title>"} + resp.status + " " + resp.reason + {"</title>
                  </head>
                  <body>
                    <h1>Error "} + resp.status + " " + resp.reason + {"</h1>
                    <p>"} + resp.reason + {"</p>
                    <h3>Guru Meditation:</h3>
                    <p>XID: "} + req.xid + {"</p>
                    <hr>
                    <p>Varnish cache server</p>
                  </body>
                </html>
                "} );
                    return (deliver);
                }
        你可以創建合成響應,例如,在vcl_synth上的個性化錯誤信息。調用這個子進程你可以做:
            return (synth(status_code, "reason"));
        註意synth不是一個關鍵字,而是個帶有參數的函數。
        你必須為vcl_synth明確地返回status code和reason參數。在resp.http上設置合成響應的頭部。
        註意:
            從 vcl/default-vcl_synth.vcl註意到 {" and "}可以用於創建多行的欄位。這個不僅限於synthetic()函數,在其他地址也可以使用。
            vcl_synth定義的對象絕不在緩存上存儲,對立與vcl_backend_error定義的對象。
        例子:
            使用vcl_synth重定向請求
                sub vcl_recv {
                    if (req.http.host == "www.example.com") {
                        set req.http.location = "http://example.com" + req.url;
                        return (synth(750, "Permanently moved"));
                    }
                }
                sub vcl_synth {
                    if (resp.status == 750) {
                        set resp.http.location = req.http.location;
                        set resp.status = 301;
                        return (deliver);
                    }
                }

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

-Advertisement-
Play Games
更多相關文章
  • 本文只講有關於在 Windows+C#中使用Redis所需要用到的資源,不涉及在C#中使用Redis的編程示例,整體過程我把它分為三個步驟,並按標題的順序逐一實現。 1、下載並安裝Redis服務 需要先下載Redis服務,並安裝於操作系統中,安裝步驟和安裝其它的Windows程式一樣,這裡就不花多餘 ...
  • CAN匯流排知識整理 一、特點 二、CAN物理層 隱性(邏輯1),顯性(邏輯0)。 三、CAN數據鏈路層 3.1通信機制 3.2數據幀 3.3錯誤幀 3.4其它幀格式 3.5位定時與同步 ...
  • pwd : print name of current/working directory 顯示路徑 ...
  • rsync是一個開源、快速的、多動能的、可以實現全量,增量的本地或遠程數據同步備份工具,它適用於多種操作系統平臺。 1、rsync的特性(功能) (1)支持拷貝特殊文件(如鏈接文件、設備文件) (2)拷貝時可以排除目錄中目錄或文件不需要同步的功能 (3)可以保持源文件或目錄的屬性不發生改變 (4)可 ...
  • 當自己認為學會了的知識並且總結後以為自己明白了這部分知識時,再次學習才發現自己認識的很片面。也許這就是要書讀百遍的意義所在吧。在學習《機器人學導論》這本書時, DH參數的建立正如公式上表達的那樣。需要有四個參數,建立坐標系時,通過在相鄰連桿的Z軸和X軸的建立,減少坐標的建立形式,在根據右手法則確定Y ...
  • 項目流程 弄清需求(需要完成什麼) 設計框架(怎麼實現需求) 編寫代碼(怎麼通過代碼設計) 測試 弄清需求 (1)上電,LCD顯示一副圖片 (2)根據配置文件,決定停留當前界面還是自動顯示下一張 (3)點擊一下,出現一個對話框(手動顯示,自動顯示) (4)上放大,下縮小,左右滑動切換圖片 (5)左右 ...
  • 一、輸出重定向 命令 > 文件 將標準輸出重定向到一個文件中(清空原有文件的數據) 命令 2> 文件 將錯誤輸出重定向到一個文件中(清空原有文件的數據) 命令 >> 文件 將標準輸出重定向到一個文件中 (追加到原有內容的後面) 命令 2>> 文件 將錯誤輸出重定向到一個文件中(追加到原有內容的後面) ...
  • Tomcat介紹 Tomcat Tomcat運行環境 Tomcat安裝運行 Tomcat程式環境 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...