【夯實Nginx基礎】Nginx工作原理和優化、漏洞

来源:http://www.cnblogs.com/aiweixiao/archive/2016/12/15/6184653.html
-Advertisement-
Play Games

本文地址 原文地址 本文提綱: 1. Nginx的模塊與工作原理 2. Nginx的進程模型 3 . NginxFastCGI運行原理 3.1 什麼是 FastCGI 3.2 NginxFastCGI運行原理 3.3 spawn-fcgi與PHP-FPM 3.4 NginxPHP-FPM 4. Ng ...


本文地址

原文地址

本文提綱

  1.  Nginx的模塊與工作原理
    2.  Nginx的進程模型
    3 . NginxFastCGI運行原理
        3.1 什麼是 FastCGI
        3.2 NginxFastCGI運行原理
        3.3 spawn-fcgi與PHP-FPM
        3.4 NginxPHP-FPM

  4. Nginx+PHP正確配置         4.1 不應該在location 模塊定義index         4.2 使用try_files         4.3 fastcgi_params配置文件       5. Nginx為啥性能高-多進程IO模型         5.1 nginx採用多進程模型好處         5.2 nginx多進程事件模型:非同步非阻塞


    6.  Nginx優化
        6.1 編譯安裝過程優化
        6.2 利用TCMalloc優化Nginx的性能
        6.3 Nginx內核參數優化
        6.4 PHP-FPM的優化
        6.5 nginxconf的參數優化

   7. 錯誤排查        7.1 Nginx 502 Bad Gateway        7.2 413 Request Entity Too Large        7.3 Ngnix error.log出現:upstream sent too big header while reading response header from upstream錯誤     8. Nginx的php漏洞

 

1.  Nginx的模塊與工作原理

第三方模塊:HTTP Upstream Request Hash模塊、Notice模塊和HTTP Access Key模塊。

圖1-1展示了Nginx模塊常規的HTTP請求和響應的過程。

Nginx本身做的工作實際很少,當它接到一個HTTP請求時,它僅僅是通過查找配置文件將此次請求映射到一個location block,而此location中所配置的各個指令則會啟動不同的模塊去完成工作,因此模塊可以看做Nginx真正的勞動工作者。通常一個location中的指令會涉及一個handler模塊和多個filter模塊(當然,多個location可以復用同一個模塊)。handler模塊負責處理請求,完成響應內容的生成,而filter模塊對響應內容進行處理。

Nginx的模塊直接被編譯進Nginx,因此屬於靜態編譯方式。啟動Nginx後,Nginx的模塊被自動載入,不像Apache,首先將模塊編譯為一個so文件,然後在配置文件中指定是否進行載入。在解析配置文件時,Nginx的每個模塊都有可能去處理某個請求,但是同一個處理請求只能由一個模塊來完成。 

 

2.  Nginx的進程模型

在工作方式上,Nginx分為單工作進程和多工作進程兩種模式。在單工作進程模式下,除主進程外,還有一個工作進程,工作進程是單線程的;在多工作進程模式下,每個工作進程包含多個線程。Nginx預設為單工作進程模式。

Nginx在啟動後,會有一個master進程和多個worker進程。

master進程

主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出後(異常情況下),會自動重新啟動新的worker進程。

master進程充當整個進程組與用戶的交互介面,同時對進程進行監護。它不需要處理網路事件,不負責業務的執行,只會通過管理worker進程來實現重啟服務、平滑升級、更換日誌文件、配置文件實時生效等功能。

我們要控制nginx,只需要通過kill向master進程發送信號就行了。比如kill -HUP pid,則是告訴nginx,從容地重啟nginx,我們一般用這個信號來重啟nginx,或重新載入配置,因為是從容地重啟,因此服務是不中斷的。master進程在接收到HUP信號後是怎麼做的呢?首先master進程在接到信號後,會先重新載入配置文件,然後再啟動新的worker進程,並向所有老的worker進程發送信號,告訴他們可以光榮退休了。新的worker在啟動後,就開始接收新的請求,而老的worker在收到來自master的信號後,就不再接收新的請求,並且在當前進程中的所有未處理完的請求處理完成後,再退出。當然,直接給master進程發送信號,這是比較老的操作方式,nginx在0.8版本之後,引入了一系列命令行參數,來方便我們管理。比如,./nginx -s reload,就是來重啟nginx,./nginx -s stop,就是來停止nginx的運行。如何做到的呢?我們還是拿reload來說,我們看到,執行命令時,我們是啟動一個新的nginx進程,而新的nginx進程在解析到reload參數後,就知道我們的目的是控制nginx來重新載入配置文件了,它會向master進程發送信號,然後接下來的動作,就和我們直接向master進程發送信號一樣了。

worker進程:

而基本的網路事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是可以設置的,一般我們會設置與機器cpu核數一致,這裡面的原因與nginx的進程模型以及事件處理模型是分不開的。

worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80埠的http服務時,一個連接請求過來,每個進程都有可能處理這個連接,怎麼做到的呢?首先,每個worker進程都是從master進程fork過來,在master進程裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。所有worker進程的listenfd會在新連接到來時變得可讀,為保證只有一個進程處理該連接,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件里調用accept接受該連接。當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80埠的http服務時,一個連接請求過來,每個進程都有可能處理這個連接,怎麼做到的呢?首先,每個worker進程都是從master進程fork過來,在master進程裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。所有worker進程的listenfd會在新連接到來時變得可讀,為保證只有一個進程處理該連接,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件里調用accept接受該連接。當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生數據後,再返回給客戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。

nginx的進程模型,可以由下圖來表示:



3.  Nginx+FastCGI運行原理

 3.1)什麼是 FastCGI

 

FastCGI介面方式採用C/S結構,可以將HTTP伺服器和腳本解析伺服器分開,同時在腳本解析伺服器上啟動一個或者多個腳本解析守護進程。當HTTP伺服器每次遇到動態程式時,可以將其直接交付給FastCGI進程來執行,然後將得到的結果返回給瀏覽器。這種方式可以讓HTTP伺服器專一地處理靜態請求或者將動態腳本伺服器的結果返回給客戶端,這在很大程度上提高了整個應用系統的性能。

 

  3.2) Nginx+FastCGI運行原理

Linux下是socket(這個socket可以是文件socket,也可以是ip socket)。

wrapper:為了調用CGI程式,還需要一個FastCGI的wrapper(wrapper可以理解為用於啟動另一個程式的程式),這個wrapper綁定在某個固定socket上,如埠或者文件socket。當Nginx將CGI請求發送給這個socket的時候,通過FastCGI介面,wrapper接收到請求,然後Fork(派生)出一個新的線程,這個線程調用解釋器或者外部程式處理腳本並讀取返回數據;接著,wrapper再將返回的數據通過FastCGI介面,沿著固定的socket傳遞給Nginx;最後,Nginx將返回的數據(html頁面或者圖片)發送給客戶端。這就是Nginx+FastCGI的整個運作過程,如圖1-3所示。

 


      所以,我們首先需要一個wrapper,這個wrapper需要完成的工作:

  1. 通過調用fastcgi(庫)的函數通過socket和ningx通信(讀寫socket是fastcgi內部實現的功能,對wrapper是非透明的)
  2. 調度thread,進行fork和kill
  3. 和application(php)進行通信

3.3)spawn-fcgi與PHP-FPM

       FastCGI介面方式在腳本解析伺服器上啟動一個或者多個守護進程對動態腳本進行解析,這些進程就是FastCGI進程管理器,或者稱為FastCGI引擎。 spawn-fcgi與PHP-FPM就是支持PHP的兩個FastCGI進程管理器。因此HTTPServer完全解放出來,可以更好地進行響應和併發處理。        spawn-fcgi與PHP-FPM的異同:
       1)spawn-fcgi是HTTP伺服器lighttpd的一部分,目前已經獨立成為一個項目,一般與lighttpd配合使用來支持PHP。但是ligttpd的spwan-fcgi在高併發訪問的時候,會出現記憶體泄漏甚至自動重啟FastCGI的問題。即:PHP腳本處理器當機,這個時候如果用戶訪問的話,可能就會出現白頁(即PHP不能被解析或者出錯)。        2)Nginx是個輕量級的HTTP server,必須藉助第三方的FastCGI處理器才可以對PHP進行解析,因此其實這樣看來nginx是非常靈活的,它可以和任何第三方提供解析的處理器實現連接從而實現對PHP的解析(nginx.conf中很容易設置)nginx也可以使用spwan-fcgi(需要一同安裝lighttpd,但是需要為nginx避開埠,一些較早的blog有這方面安裝的教程),但是由於spawn-fcgi具有上面所述的用戶逐漸發現的缺陷,現在慢慢減少用nginx+spawn-fcgi組合了。

       由於spawn-fcgi的缺陷,現在出現了第三方(目前已經加入到PHP core中)的PHP的FastCGI處理器PHP-FPM,它和spawn-fcgi比較起來有如下優點:

       由於它是作為PHP的patch補丁來開發的,安裝的時候需要和php源碼一起編譯,也就是說編譯到php core中了,因此在性能方面要優秀一些;

同時它在處理高併發方面也優於spawn-fcgi,至少不會自動重啟fastcgi處理器。因此,推薦使用Nginx+PHP/PHP-FPM這個組合對PHP進行解析。

      相對Spawn-FCGI,PHP-FPM在CPU和記憶體方面的控制都更勝一籌,而且前者很容易崩潰,必須用crontab進行監控,而PHP-FPM則沒有這種煩惱。
       FastCGI 的主要優點是把動態語言和HTTP Server分離開來,所以Nginx與PHP/PHP-FPM經常被部署在不同的伺服器上,以分擔前端Nginx伺服器的壓力,使Nginx專一處理靜態請求和轉發動態請求,而PHP/PHP-FPM伺服器專一解析PHP動態請求。

3.4) Nginx+PHP-FPM

      PHP-FPM是管理FastCGI的一個管理器,它作為PHP的插件存在,在安裝PHP要想使用PHP-FPM時在老php的老版本(php5.3.3之前)就需要把PHP-FPM以補丁的形式安裝到PHP中,而且PHP要與PHP-FPM版本一致,這是必須的)

 

   PHP-FPM其實是PHP源代碼的一個補丁,旨在將FastCGI進程管理整合進PHP包中。必須將它patch到你的PHP源代碼中,在編譯安裝PHP後才可以使用。
   PHP5.3.3已經集成php-fpm了,不再是第三方的包了。PHP-FPM提供了更好的PHP進程管理方式,可以有效控制記憶體和進程、可以平滑重載PHP配置,比spawn-fcgi具有更多優點,所以被PHP官方收錄了。在./configure的時候帶 –enable-fpm參數即可開啟PHP-FPM。

      fastcgi已經在php5.3.5的core中了,不必在configure時添加 --enable-fastcgi了。老版本如php5.2的需要加此項。

      當我們安裝Nginx和PHP-FPM完後,配置信息:

PHP-FPM的預設配置php-fpm.conf      listen_address  127.0.0.1:9000 #這個表示php的fastcgi進程監聽的ip地址以及埠 start_servers       min_spare_servers       max_spare_servers
 Nginx配置運行php: 編輯nginx.conf加入如下語句:       location ~ \.php$ {
            root html;   
            fastcgi_pass 127.0.0.1:9000; 指定了fastcgi進程偵聽的埠,nginx就是通過這裡與php交互的
            fastcgi_index index.php;
            include fastcgi_params;
             fastcgi_param SCRIPT_FILENAME   /usr/local/nginx/html$fastcgi_script_name;
    }
    Nginx通過location指令,將所有以php為尾碼的文件都交給127.0.0.1:9000來處理,而這裡的IP地址和埠就是FastCGI進程監聽的IP地址和埠。          其整體工作流程:      1)、FastCGI進程管理器php-fpm自身初始化,啟動主進程php-fpm和啟動start_servers個CGI 子進程。            主進程php-fpm主要是管理fastcgi子進程,監聽9000埠。            fastcgi子進程等待來自Web Server的連接。      2)、當客戶端請求到達Web Server Nginx是時,Nginx通過location指令,將所有以php為尾碼的文件都交給127.0.0.1:9000來處理,即Nginx通過location指令,將所有以php為尾碼的文件都交給127.0.0.1:9000來處理。       3)FastCGI進程管理器PHP-FPM選擇並連接到一個子進程CGI解釋器。Web server將CGI環境變數和標準輸入發送到FastCGI子進程。       4)、FastCGI子進程完成處理後將標準輸出和錯誤信息從同一連接返回Web Server。當FastCGI子進程關閉連接時,請求便告處理完成。       5)、FastCGI子進程接著等待並處理來自FastCGI進程管理器(運行在 WebServer中)的下一個連接。

4.   Nginx+PHP正確配置

一般web都做統一入口:把PHP請求都發送到同一個文件上,然後在此文件里通過解析「REQUEST_URI」實現路由。

Nginx配置文件分為好多塊,常見的從外到內依次是「http」、「server」、「location」等等,預設的繼承關係是從外到內,也就是說內層塊會自動獲取外層塊的值作為預設值。

例如:

 

[plain] view plain copy print?
  1. server {  
  2.     listen 80;  
  3.     server_name foo.com;  
  4.     root /path;  
  5.     location / {  
  6.         index index.html index.htm index.php;  
  7.         if (!-e $request_filename) {  
  8.             rewrite . /index.php last;  
  9.         }  
  10.     }  
  11.     location ~ \.php$ {  
  12.         include fastcgi_params;  
  13.         fastcgi_param SCRIPT_FILENAME /path$fastcgi_script_name;  
  14.         fastcgi_pass 127.0.0.1:9000;  
  15.         fastcgi_index index.php;  
  16.     }  
  17. }   

4.1)  不應該在location 模塊定義index

一旦未來需要加入新的「location」,必然會出現重覆定義的「index」指令,這是因為多個「location」是平級的關係,不存在繼承,此時應該在「server」里定義「index」,藉助繼承關係,「index」指令在所有的「location」中都能生效。

4.2)     使用try_files

接下來看看「if」指令,說它是大家誤解最深的Nginx指令毫不為過:

if (!-e $request_filename) {

rewrite . /index.php last;

}

很多人喜歡用「if」指令做一系列的檢查,不過這實際上是「try_files」指令的職責:

try_files $uri $uri/ /index.php;


除此以外,初學者往往會認為「if」指令是內核級的指令,但是實際上它是rewrite模塊的一部分,加上Nginx配置實際上是聲明式的,而非過程式的,所以當其和非rewrite模塊的指令混用時,結果可能會非你所願。


4.3) fastcgi_params」配置文件

include fastcgi_params;

Nginx有兩份fastcgi配置文件,分別是「fastcgi_params」和「fastcgi.conf」,它們沒有太大的差異,唯一的區別是後者比前者多了一行「SCRIPT_FILENAME」的定義:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


註意:$document_root 和 $fastcgi_script_name 之間沒有 /。

原本Nginx只有「fastcgi_params」,後來發現很多人在定義「SCRIPT_FILENAME」時使用了硬編碼的方式,於是為了規範用法便引入了「fastcgi.conf」。


不過這樣的話就產生一個疑問:為什麼一定要引入一個新的配置文件,而不是修改舊的配置文件?這是因為「fastcgi_param」指令是數組型的,和普通指令相同的是:內層替換外層;和普通指令不同的是:當在同級多次使用的時候,是新增而不是替換。換句話說,如果在同級定義兩次「SCRIPT_FILENAME」,那麼它們都會被髮送到後端,這可能會導致一些潛在的問題,為了避免此類情況,便引入了一個新的配置文件。


此外,我們還需要考慮一個安全問題:在PHP開啟「cgi.fix_pathinfo」的情況下,PHP可能會把錯誤的文件類型當作PHP文件來解析。如果Nginx和PHP安裝在同一臺伺服器上的話,那麼最簡單的解決方法是用「try_files」指令做一次過濾:


try_files $uri =404;

依照前面的分析,給出一份改良後的版本,是不是比開始的版本清爽了很多:

 

[plain] view plain copy print?
  1. server {  
  2.     listen 80;  
  3.     server_name foo.com;  
  4.     root /path;  
  5.     index index.html index.htm index.php;  
  6.     location / {  
  7.         try_files $uri $uri/ /index.php;  
  8.     }  
  9.     location ~ \.php$ {  
  10.        try_files $uri =404;  
  11.        include fastcgi.conf;  
  12.        fastcgi_pass 127.0.0.1:9000;  
  13.    }  
  14. }  



 

5.   Nginx為啥性能高-多進程IO模型

      參考文章:http://mp.weixin.qq.com/s?__biz=MjM5NTg2NTU0Ng==&mid=407889757&idx=3&sn=cfa8a70a5fd2a674a91076f67808273c&scene=23&srcid=0401aeJQEraSG6uvLj69Hfve#rd

5.1) nginx採用多進程模型好處

      首先,對於每個worker進程來說,獨立的進程,不需要加鎖,所以省掉了鎖帶來的開銷,同時在編程以及問題查找時,也會方便很多。

      其次,採用獨立的進程,可以讓互相之間不會影響,一個進程退出後,其它進程還在工作,服務不會中斷,master進程則很快啟動新的worker進程。當然,worker進程的異常退出,肯定是程式有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風險。

5.2) nginx多進程事件模型:非同步非阻塞

         雖然nginx採用多worker的方式來處理請求,每個worker裡面只有一個主線程,那能夠處理的併發數很有限啊,多少個worker就能處理多少個併發,何來高併發呢?非也,這就是nginx的高明之處,nginx採用了非同步非阻塞的方式來處理請求,也就是說,nginx是可以同時處理成千上萬個請求的。一個worker進程可以同時處理的請求數只受限於記憶體大小,而且在架構設計上,不同的worker進程之間處理併發請求時幾乎沒有同步鎖的限制,worker進程通常不會進入睡眠狀態,因此,當Nginx上的進程數與CPU核心數相等時(最好每一個worker進程都綁定特定的CPU核心),進程間切換的代價是最小的。

       而apache的常用工作方式(apache也有非同步非阻塞版本,但因其與自帶某些模塊衝突,所以不常用),每個進程在一個時刻只處理一個請求,因此,當併發數上到幾千時,就同時有幾千的進程在處理請求了。這對操作系統來說,是個不小的挑戰,進程帶來的記憶體占用非常大,進程的上下文切換帶來的cpu開銷很大,自然性能就上不去了,而這些開銷完全是沒有意義的。

     


         為什麼nginx可以採用非同步非阻塞的方式來處理呢,或者非同步非阻塞到底是怎麼回事呢?

         我們先回到原點,看看一個請求的完整過程:首先,請求過來,要建立連接,然後再接收數據,接收數據後,再發送數據。

         具體到系統底層,就是讀寫事件,而當讀寫事件沒有準備好時,必然不可操作,如果不用非阻塞的方式來調用,那就得阻塞調用了,事件沒有準備好,那就只能等了,等事件準備好了,你再繼續吧。阻塞調用會進入內核等待,cpu就會讓出去給別人用了,對單線程的worker來說,顯然不合適,當網路事件越多時,大家都在等待呢,cpu空閑下來沒人用,cpu利用率自然上不去了,更別談高併發了。好吧,你說加進程數,這跟apache的線程模型有什麼區別,註意,別增加無謂的上下文切換。所以,在nginx裡面,最忌諱阻塞的系統調用了。不要阻塞,那就非阻塞嘍。非阻塞就是,事件沒有準備好,馬上返回EAGAIN,告訴你,事件還沒準備好呢,你慌什麼,過會再來吧。好吧,你過一會,再來檢查一下事件,直到事件準備好了為止,在這期間,你就可以先去做其它事情,然後再來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態,你可以做更多的事情了,但帶來的開銷也是不小的。

關於IO模型:http://blog.csdn.NET/hguisu/article/details/7453390

       nginx支持的事件模型如下(nginx的wiki):

       Nginx支持如下處理連接的方法(I/O復用方法),這些方法可以通過use指令指定。

  • select– 標準方法。 如果當前平臺沒有更有效的方法,它是編譯時預設的方法。你可以使用配置參數 –with-select_module 和 –without-select_module 來啟用或禁用這個模塊。
  • poll– 標準方法。 如果當前平臺沒有更有效的方法,它是編譯時預設的方法。你可以使用配置參數 –with-poll_module 和 –without-poll_module 來啟用或禁用這個模塊。
  • kqueue– 高效的方法,使用於 FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X. 使用雙處理器的MacOS X系統使用kqueue可能會造成內核崩潰。
  • epoll – 高效的方法,使用於Linux內核2.6版本及以後的系統。在某些發行版本中,如SuSE 8.2, 有讓2.4版本的內核支持epoll的補丁。
  • rtsig – 可執行的實時信號,使用於Linux內核版本2.2.19以後的系統。預設情況下整個系統中不能出現大於1024個POSIX實時(排隊)信號。這種情況 對於高負載的伺服器來說是低效的;所以有必要通過調節內核參數 /proc/sys/kernel/rtsig-max 來增加隊列的大小。可是從Linux內核版本2.6.6-mm2開始, 這個參數就不再使用了,並且對於每個進程有一個獨立的信號隊列,這個隊列的大小可以用 RLIMIT_SIGPENDING 參數調節。當這個隊列過於擁塞,nginx就放棄它並且開始使用 poll 方法來處理連接直到恢復正常。
  • /dev/poll – 高效的方法,使用於 Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+.
  • eventport – 高效的方法,使用於 Solaris 10. 為了防止出現內核崩潰的問題, 有必要安裝
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #相當於對數據 加上 雙引號,$相當於直接顯示數據 1. #將傳入的數據都當成一個字元串,會對自動傳入的數據加一個雙引號。如:order by #user_id#,如果傳入的值是111,那麼解析成sql時的值為order by "111", 如果傳入的值是id,則解析成的sql為order by " ...
  • 問題描述: 在case語句中,這樣寫,編譯時,會提示變數unsafe,解決編譯器報錯的方法有下麵兩個: 1、給unsafe的變數賦值 case get(?Player_LoopTaskInfo) of {TargetCnt, TaskStar, TaskExp} -> ok; _ -> Target ...
  • 一、Memcached Memcached 是一個高性能的分散式記憶體對象緩存系統,用於動態Web應用以減輕資料庫負載。它通過在記憶體中緩存數據和對象來減少讀取資料庫的次數,從而提高動態、資料庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的 ...
  • 1041. 考試座位號(15) 每個PAT考生在參加考試時都會被分配兩個座位號,一個是試機座位,一個是考試座位。正常情況下,考生在入場時先得到試機座位號碼,入座進入試機狀態後,系統會顯示該考生的考試座位號碼,考試時考生需要換到考試座位就座。但有些考生遲到了,試機已經結束,他們只能拿著領到的試機座位號 ...
  • 1016. 部分A+B (15) 正整數A的“DA(為1位整數)部分”定義為由A中所有DA組成的新整數PA。例如:給定A = 3862767,DA = 6,則A的“6部分”PA是66,因為A中有2個6。 現給定A、DA、B、DB,請編寫程式計算PA + PB。 輸入格式: 輸入在一行中依次給出A、D ...
  • 1054. 求平均值 (20) 本題的基本要求非常簡單:給定N個實數,計算它們的平均值。但複雜的是有些輸入數據可能是非法的。一個“合法”的輸入是[-1000,1000]區間內的實數,並且最多精確到小數點後2位。當你計算平均值的時候,不能把那些非法的數據算在內。 輸入格式: 輸入第一行給出正整數N(< ...
  • 讀入一個自然數n,計算其各位數字之和,用漢語拼音寫出和的每一位數字。 輸入格式:每個測試輸入包含1個測試用例,即給出自然數n的值。這裡保證n小於10100。 輸出格式:在一行內輸出n的各位數字之和的每一位,拼音數字間有1 空格,但一行中最後一個拼音數字後沒有空格。 輸入樣例: 輸出樣例: ...
  • 1.自我介紹。2.占領腦袋和丟了腳3.物聯的現實困難4.效率與成本5.智能網關,跑Windows 10 IOT和Ubuntu Mate6.SuperIO到ServerSuperIO發展歷程和解決的實現問題7.一套設備驅動,支持多種IO通訊8.一套設備驅動,統一介面,多種平臺掛載運行9.物聯通訊的級聯... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...