Jmeter(五) – 從入門到精通 – 創建網絡計劃實戰和創建高級Web測試計劃(詳解教程),Jmeter(三) – 從入門到精通 – 測試計劃(Test Plan)的元件(詳解教程),Jmeter(三) – 從入門到精通 – 測試計劃(Test Plan)的元件(詳解教程)_台北網頁設計

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

1.簡介

  上一篇中宏哥已經將其的理論知識介紹了一下,這一篇宏哥就帶着大家一步一步的把上一篇介紹的理論知識實踐一下,然後再說一下如何創建高級web測試計劃。

2.網絡計劃實戰

  通過上一篇的學習,宏哥將其分類為:

    (1)不需要登錄驗證身份就可以操作的。

    (2)需要登錄驗證身份之後才能操作的。

2.1不需要登錄

這裏宏哥就拿博客園來舉例子,如博客園,你不需要登錄驗證身份,就可以執行閱讀、查找和瀏覽博客園內的文章(前提是這些文章沒有設置“只允許註冊的用戶訪問”)。

2.1.1抓包

1.閱讀博客園文章

1、瀏覽器上輸入博客園地址,點擊文章::Jmeter(三) – 從入門到精通 – 測試計劃(Test Plan)的元件(詳解教程),如下圖所示:

2、fiddler抓包工具抓取博客園查找的過程。從下圖紅色圈住的部分可以看到查找的URL和請求查找發送的參數。如下圖所示:

2.1.2閱讀文章

按照抓包抓取到的參數,我們下一步就是用Jmeter模擬閱讀博客園文章:Jmeter(三) – 從入門到精通 – 測試計劃(Test Plan)的元件(詳解教程)。

1.建立一個測試計劃命名為:Test Blog Read Plan。如圖下所示:

2.選中測試計劃,添加線程組用戶,命名為:Blog User。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥這個就是一個用戶閱讀一次,如果要壓測你可以設置多個用戶同時閱讀。

3.選中線程組,添加一個HTTP Header Manager(HTTP信息頭管理器)。這個主要是為了避免Jmeter發送請求后,返回結果可能會出現狀態碼為403的錯誤。如下圖所示:

注意:敲腦殼,敲黑板啦!!!這裏HTTP信息頭管理器,主要添加一個參數User-Agent。根據你抓包的header來填寫即可。

4.選中線程組,設置一個http,發送http默認請求值,放入你需求測試的地址。這樣做的好處就是後邊的所有的http請求你就不再需要重複的寫這個測試地址了。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥本地搭建的Jenkins應用程序,那麼測試地址就很清楚了,這裏請求值填寫如下:

(1)protocol(協議:http or https):目前博客園是https協議,所以這裏填寫Protocol:https

(2)測試地址為:博客園的地址,不用啰嗦大家都知道了,Sever Name or IP:www.cnblogs.com

(3)Port:(博客園沒有端口)

5.選中線程組,添加一個http請求命名為:Read。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥本地搭建的Jenkins應用程序,那麼Read請求值,我們查看抓到登錄請求包(2.2.1)就很清楚了,這裏請求值填寫如下:

(1)protocol(協議:http or https):目前這個是本地搭建的http協議,所以這裏填寫Protocol:https

(2)測試地址為:本地搭建,不用啰嗦大家都知道了,Sever Name or IP:www.cnblogs.com

(3)Port:(博客園沒有端口)

(4)Method:是那種類型的請求就選擇那種,這裏選擇get

(5)Path:閱讀博客園文章的請求路徑

(6)Content Encoding:編碼宏哥這裏沒有填寫,如果出現亂碼,你可以填寫utf-8和Gb2312試一下,即可。

6.選中線程組,添加一個結果樹,命名為:Check Read Results,監聽閱讀博文是否成功。如下圖所示:

2.2需要登錄

同樣的這裏也拿博客園舉例子,你如果要發布隨筆、評論、點推薦等等的一系列操作,就需要你登錄驗證身份以後才能執行這些操作。但是由於博客園的登錄機制改變宏哥就不拿博客園舉例子,宏哥拿一個,宏哥在本地搭建的Jenkins的web應用程序來實戰一下,刪除一個job。但是這個job必須在登錄以後才能刪除,如果沒有登錄就會刪除失敗。

2.2.1抓包

1.登錄

1、瀏覽器上登錄jenkins,輸入賬號和密碼,點擊登錄。如下圖所示:

2、fiddler抓包工具抓取jenkins登錄的過程。從下圖紅色圈住的部分可以看到登錄的URL和請求登錄發送的參數。如下圖所示:

2.刪除

1、我們前面講過登錄后新建任務后,那可以繼續接着操作:刪除剛才新建的任務。如下圖所示:

 

2、用fiddler抓包,抓到刪除新建任務的請求,從抓包結果可以看出,傳的data參數是Jenkins-Crumb。如下圖所示:

 

3.這個Jenkins-Crumb哪裡來的呢?可以看上個請求的body。如下圖所示:

2.2.2登錄

按照抓包抓取到的參數,我們下一步就是用Jmeter模擬登錄到Jenkins。

1.建立一個測試計劃命名為:Test Jenkins Plan。如下圖所示:

2.選中測試計劃,添加線程組用戶,命名為:Jenkins User。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥這個就是一個用戶登錄一次,如果要壓測你可以設置多個用戶同時登錄。

3.選中線程組,添加一個HTTP Header Manager(HTTP信息頭管理器)。這個主要是為了避免Jmeter發送請求后,返回結果可能會出現狀態碼為403的錯誤。如下圖所示:

注意:敲腦殼,敲黑板啦!!!這裏HTTP信息頭管理器,主要添加兩個參數User-Agent和Content-Type。根據你抓包的header來填寫即可。

4.選中線程組,設置一個http,發送http默認請求值,放入你需求測試的地址。這樣做的好處就是後邊的所有的http請求你就不再需要重複的寫這個測試地址了。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥本地搭建的Jenkins應用程序,那麼測試地址就很清楚了,這裏請求值填寫如下:

(1)protocol(協議:http or https):目前這個是本地搭建的http協議,所以這裏填寫Protocol:http

(2)測試地址為:本地搭建,不用啰嗦大家都知道了,Sever Name or IP:localhost

(3)Port:8080(這裏宏哥搭建的默認端口8080,你也可以在Tomcat的配置文件修改這個端口)

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

5.選中線程組,添加一個http請求命名為:Login。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥本地搭建的Jenkins應用程序,那麼Login請求值,我們查看抓到登錄請求包(2.2.1)就很清楚了,這裏請求值填寫如下:

(1)protocol(協議:http or https):目前這個是本地搭建的http協議,所以這裏填寫Protocol:http

(2)測試地址為:本地搭建,不用啰嗦大家都知道了,Sever Name or IP:localhost

(3)Port:8080(這裏宏哥搭建的默認端口8080,你也可以在Tomcat的配置文件修改這個端口)

(4)Method:是那種類型的請求就選擇那種,這裏選擇post

(5)Path:登錄的請求路徑

(6)Content Encoding:編碼宏哥這裏沒有填寫,如果出現亂碼,你可以填寫utf-8和Gb2312試一下,即可。

6.選中線程組,添加一個cookie管理器,用來管理登錄后的cookie。如下圖所示:

注意:敲腦殼,敲黑板啦!!!cookie的添加一個值,這個也可以在抓包登陸請求中header查看到,這裏宏哥就不細說了。

(1)Name:JSESSIONID

(2)Value:一串数字和字母

(3)Domain:localhost

7.選中線程組,添加一個結果樹,命名為:Check Login Results,監聽登錄是否成功。如下圖所示:

8.選中線程組,添加一個http請求命名為:Delete Item。如下圖所示:

注意:敲腦殼,敲黑板啦!!!宏哥本地搭建的Jenkins應用程序,那麼Delete請求值,我們查看抓到刪除請求包(2.2.1)就很清楚了,這裏請求值填寫如下:

(1)protocol(協議:http or https):目前這個是本地搭建的http協議,所以這裏填寫Protocol:http

(2)測試地址為:本地搭建,不用啰嗦大家都知道了,Sever Name or IP:localhost

(3)Port:8080(這裏宏哥搭建的默認端口8080,你也可以在Tomcat的配置文件修改這個端口)

(4)Method:是那種類型的請求就選擇那種,這裏選擇post

(5)Path:刪除的請求路徑

(6)Content Encoding:編碼宏哥這裏沒有填寫,如果出現亂碼,你可以填寫utf-8和Gb2312試一下,即可。

9.選中線程組,添加一個結果樹,命名為:Check Delete Results,監聽刪除job是否成功。如下圖所示:

2.3JMeter運行查看運行結果

2.3.1不需要登錄

1、點擊綠色的按鈕,運行Jmeter,如下圖所示:

 2、查看JMeter運行結果,一個請求的監聽結果都是綠色的,說明請求成功。如下圖所示:

 (1)查看閱讀是否成功,從結果看到博文內容,說明閱讀成功。如下圖所示:

2.3.2登錄

1、Jenkins的新建任務里有“北京-宏哥”,如下圖所示:

2、點擊綠色的按鈕,運行Jmeter,如下圖所示:

 3、查看JMeter運行結果,兩個請求的監聽結果都是綠色的,說明請求成功。如下圖所示:

(1)查看登錄是否成功,從結果看到“admin”和“註銷”,說明登錄成功。如下圖所示:

(2)可以看到登錄成功后的,任務中有“北京-宏哥”。如下圖所示:

(3)查看刪除是否成功,從結果中沒有看到“北京-宏哥”,說明刪除成功。如下圖所示:

4、查看Jenkins的新建任務,沒有看到“北京-宏哥”,說明刪除成功了,如下圖所示:

3.制定高級Web測試計劃

在本小節中,紅兒將介紹一下如何創建高級 測試計劃來測試網站。

有關基本測試計劃的示例,請參閱構建Web測試計劃

3.1使用URL重寫處理用戶會話

如果您的Web應用程序使用URL重寫而不是Cookie來保存會話信息,則您需要做一些額外的工作來測試您的站點。

為了正確響應URL重寫,JMeter需要解析從服務器接收的HTML並檢索唯一的會話ID。使用適當的HTTP URL重寫修飾符 可以完成此操作。只需將您的會話ID參數的名稱輸入到修飾符中,它將找到它並將其添加到每個請求中。如果請求已經有一個值,它將被替換。如果是“緩存會話ID?” 如果選中,則將保存最後找到的會話ID,如果先前的HTTP示例不包含會話ID,則將使用該ID。

URL重寫示例

下載此示例在圖1中显示了使用URL重寫的測試計劃。請注意,URL Re-writing修飾符已添加到SimpleController中,從而確保它只會影響該SimpleController下的請求。

圖1-測試樹

在圖2中,我們看到URL重寫修飾符GUI,它只有一個字段供用戶指定會話ID參數的名稱。還有一個複選框,用於指示會話ID應該是路徑的一部分(用“;”分隔),而不是請求參數。

圖2-請求參數

3.2使用標題管理器

HTTP頭管理器可以讓你定製什麼樣的信息JMeter的HTTP請求頭髮送。此標頭包含“用戶代理”,“編譯指示”,“推薦人”等屬性。

該HTTP頭管理器,像HTTP Cookie管理器,可能應該在線程組級別添加,除非出於某種原因,您希望為不同的指定不同的頁眉HTTP請求在您的測試對象。

4.小結

4.1登錄和刪除前三個參數空白

1.細心地小夥伴或者童鞋們會從截圖中發現宏哥的登錄和刪除的前三個參數都是空白的,什麼也沒有填寫,那是因為前邊的HTTP默認請求,所以這裏不用填寫,好處就從這裏就看出來了,目前只是列舉了兩個請求,如果成百上千的請求是不是效果就更明顯了。

 

   好了,今天有關創建網絡計劃實戰和創建高級Web測試計劃就分享到這裏。灰常感謝您閱讀到這裏,如果您覺得不錯,就幫忙點個推薦唄。

您的肯定就是我進步的動力。如果你感覺還不錯,就請鼓勵一下吧!記得隨手點波  推薦  不要忘記哦!!!

別忘了點 推薦 留下您來過的痕迹

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

Redis詳解(十一)—— 過期刪除策略和內存淘汰策略_網頁設計公司

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

  在介紹這篇文章之前,我們先來看如下幾個問題:

  ①、如何設置Redis鍵的過期時間?

  ②、設置完一個鍵的過期時間后,到了這個時間,這個鍵還能獲取到么?假如獲取不到那這個鍵還佔據着內存嗎?

  ③、如何設置Redis的內存大小?當內存滿了之後,Redis有哪些內存淘汰策略?我們又該如何選擇?

  如果上面的幾個問題你都懂,那麼下面的內容你就不用看了;如果你不是很懂,那就帶着這些問題往下看。

1、設置Redis鍵過期時間

  Redis提供了四個命令來設置過期時間(生存時間)。

  ①、EXPIRE <key> <ttl> :表示將鍵 key 的生存時間設置為 ttl 秒。

  ②、PEXPIRE <key> <ttl> :表示將鍵 key 的生存時間設置為 ttl 毫秒。

  ③、EXPIREAT <key> <timestamp> :表示將鍵 key 的生存時間設置為 timestamp 所指定的秒數時間戳。

  ④、PEXPIREAT <key> <timestamp> :表示將鍵 key 的生存時間設置為 timestamp 所指定的毫秒數時間戳。

  PS:在Redis內部實現中,前面三個設置過期時間的命令最後都會轉換成最後一個PEXPIREAT 命令來完成。

  另外補充兩個知識點:

  一、移除鍵的過期時間

  PERSIST <key> :表示將key的過期時間移除。

  二、返回鍵的剩餘生存時間

  TTL <key> :以秒的單位返回鍵 key 的剩餘生存時間。

  PTTL <key> :以毫秒的單位返回鍵 key 的剩餘生存時間。

2、Redis過期時間的判定

  在Redis內部,每當我們設置一個鍵的過期時間時,Redis就會將該鍵帶上過期時間存放到一個過期字典中。當我們查詢一個鍵時,Redis便首先檢查該鍵是否存在過期字典中,如果存在,那就獲取其過期時間。然後將過期時間和當前系統時間進行比對,比系統時間大,那就沒有過期;反之判定該鍵過期。

3、過期刪除策略

  通常刪除某個key,我們有如下三種方式進行處理。

①、定時刪除

  在設置某個key 的過期時間同時,我們創建一個定時器,讓定時器在該過期時間到來時,立即執行對其進行刪除的操作。

  優點:定時刪除對內存是最友好的,能夠保存內存的key一旦過期就能立即從內存中刪除。

  缺點:對CPU最不友好,在過期鍵比較多的時候,刪除過期鍵會佔用一部分 CPU 時間,對服務器的響應時間和吞吐量造成影響。

②、惰性刪除

  設置該key 過期時間后,我們不去管它,當需要該key時,我們在檢查其是否過期,如果過期,我們就刪掉它,反之返回該key。

  優點:對 CPU友好,我們只會在使用該鍵時才會進行過期檢查,對於很多用不到的key不用浪費時間進行過期檢查。

  缺點:對內存不友好,如果一個鍵已經過期,但是一直沒有使用,那麼該鍵就會一直存在內存中,如果數據庫中有很多這種使用不到的過期鍵,這些鍵便永遠不會被刪除,內存永遠不會釋放。從而造成內存泄漏。

③、定期刪除

  每隔一段時間,我們就對一些key進行檢查,刪除裏面過期的key。

  優點:可以通過限制刪除操作執行的時長和頻率來減少刪除操作對 CPU 的影響。另外定期刪除,也能有效釋放過期鍵佔用的內存。

  缺點:難以確定刪除操作執行的時長和頻率。

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

     如果執行的太頻繁,定期刪除策略變得和定時刪除策略一樣,對CPU不友好。

     如果執行的太少,那又和惰性刪除一樣了,過期鍵佔用的內存不會及時得到釋放。

     另外最重要的是,在獲取某個鍵時,如果某個鍵的過期時間已經到了,但是還沒執行定期刪除,那麼就會返回這個鍵的值,這是業務不能忍受的錯誤。

4、Redis過期刪除策略

  前面討論了刪除過期鍵的三種策略,發現單一使用某一策略都不能滿足實際需求,聰明的你可能想到了,既然單一策略不能滿足,那就組合來使用吧。

  沒錯,Redis的過期刪除策略就是:惰性刪除和定期刪除兩種策略配合使用。

  惰性刪除:Redis的惰性刪除策略由 db.c/expireIfNeeded 函數實現,所有鍵讀寫命令執行之前都會調用 expireIfNeeded 函數對其進行檢查,如果過期,則刪除該鍵,然後執行鍵不存在的操作;未過期則不作操作,繼續執行原有的命令。

  定期刪除:由redis.c/activeExpireCycle 函數實現,函數以一定的頻率運行,每次運行時,都從一定數量的數據庫中取出一定數量的隨機鍵進行檢查,並刪除其中的過期鍵。

  注意:並不是一次運行就檢查所有的庫,所有的鍵,而是隨機檢查一定數量的鍵。

  定期刪除函數的運行頻率,在Redis2.6版本中,規定每秒運行10次,大概100ms運行一次。在Redis2.8版本后,可以通過修改配置文件redis.conf 的 hz 選項來調整這個次數。

  

 

  看上面對這個參數的解釋,建議不要將這個值設置超過 100,否則會對CPU造成比較大的壓力。

  我們看到,通過過期刪除策略,對於某些永遠使用不到的鍵,並且多次定期刪除也沒選定到並刪除,那麼這些鍵同樣會一直駐留在內存中,又或者在Redis中存入了大量的鍵,這些操作可能會導致Redis內存不夠用,這時候就需要Redis的內存淘汰策略了。

5、內存淘汰策略

①、設置Redis最大內存

  在配置文件redis.conf 中,可以通過參數 maxmemory <bytes> 來設定最大內存:

  

  不設定該參數默認是無限制的,但是通常會設定其為物理內存的四分之三。(這裡有個疑惑:為啥作者不考慮將此參數設定為百分比呢?)

②、設置內存淘汰方式

  當現有內存大於 maxmemory 時,便會觸發redis主動淘汰內存方式,通過設置 maxmemory-policy ,有如下幾種淘汰方式:

  1)volatile-lru   利用LRU算法移除設置過過期時間的key (LRU:最近使用 Least Recently Used ) 。

  2)allkeys-lru   利用LRU算法移除任何key (和上一個相比,刪除的key包括設置過期時間和不設置過期時間的)。通常使用該方式

  3)volatile-random 移除設置過過期時間的隨機key 。

  4)allkeys-random  無差別的隨機移除。

  5)volatile-ttl   移除即將過期的key(minor TTL) 

  6)noeviction 不移除任何key,只是返回一個寫錯誤 ,默認選項,一般不會選用。

  在redis.conf 配置文件中,可以設置淘汰方式:

  

6、總結

  通過上面的介紹,相信大家對Redis的過期數據刪除策略和內存淘汰策略有一定的了解了。這裏總結一下:

  Redis過期刪除策略是採用惰性刪除和定期刪除這兩種方式組合進行的,惰性刪除能夠保證過期的數據我們在獲取時一定獲取不到,而定期刪除設置合適的頻率,則可以保證無效的數據及時得到釋放,而不會一直佔用內存數據。

  但是我們說Redis是部署在物理機上的,內存不可能無限擴充的,當內存達到我們設定的界限后,便自動觸發Redis內存淘汰策略,而具體的策略方式要根據實際業務情況進行選取。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

武漢市發熱門診就診高峰全天超1.5萬人_租車

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

新華社武漢1月27日電(記者王作葵、喻珮)武漢市發熱門診就診人數增加,過去幾天的高峰時段,一天就診人數超過1.5萬人,全市發熱門診超負荷運轉。這是武漢市委書記馬國強27日晚在湖北新型冠狀病毒感染的肺炎疫情防控工作例行新聞發布會上說的。

馬國強說,往年同期,武漢市發熱門診日均就診人數在3000例左右。疫情發生以來,發熱門診就診人數逐日增多,高峰時段超過了1.5萬人。儘管發熱門診超負荷運轉,前期一些地方還是出現大量人員排隊的現象。

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

“武漢市全市現有62家醫院設置發熱門診,但是由於其分佈不同、知名度不同,大家普遍希望到大醫院、有名的醫院去就診。”馬國強說,前期出現的發熱門診排長隊情況現已有所緩解。

湖北省醫療救治組專家、湖北省人民醫院呼吸科教授胡克說,由於前期診斷的新型冠狀病毒感染的肺炎病例少,出院的病例相對也較少。隨着後期診斷和治療跟進,出院病例數將逐步增加。

他介紹,病毒性肺炎的治療周期在2到3周。為了確保新型冠狀病毒感染的肺炎患者在出院后不具有傳染性,需要進行相應的檢測。要求體溫恢復正常3天以上,呼吸道癥狀明顯好轉,肺部影像學显示炎症明顯吸收,連續2次呼吸道病原核酸檢測陰性,且採樣間隔時間至少在1天以上。符合這些要求才可以解除隔離出院。

本站聲明:網站內容來http://www.societynews.cn/html/wh/fq/,如有侵權,請聯繫我們,我們將及時處理

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

WWDC2022登場?下代Mac Pro規格曝光 最高內建64核ARM處理器_網頁設計

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

就在蘋果分手Intel,推出首款專為Mac設計的M1晶片,取得巨大的成功之時。蘋果爆料大神LeaksApplePro就在推特上表示,蘋果目前正在著手研發下一代的Mac Pro,新一代的Mac Pro預計在WWDC 2022正式問世,將會內建16、32、64核處理器。

根據蘋果官網資料顯示,目前Mac Pro最高可以搭載Intel Xeon W 2.5GHz 28核心處理器,記憶體最高可安裝1.5TB(12條128GB DIMM)、儲存裝置為8TB SSD,而顯示部分最高可採用兩張Radeon Pro Vega II Duo 32GB顯示卡。

而下一代的Mac Pro規格,根據爆料大神LeaksApplePro的內容,除了會在 WWDC 2022公布之外,處理器部分會有16、32、64核三種處理器,記憶體則是維持原有的最高可安裝至 1.5TB,但最高儲存空間則翻倍成為16TB SSD。

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

雖然顯示卡部分並沒有透漏,但根據先前《彭博社》的報導指出,蘋果正在開發128核心GPU所組成的SoC,希望能藉此擺脫對Intel處理器與AMD顯示卡的依賴。除此之外,蘋果另外還會推出由8、12、16核心 CPU,配合16、32、64核心GPU,來組成各種SoC產品進行販售,而《彭博社》相信128核心GPU所組成的SoC將會優先使用在蘋果的頂級電腦機種Mac Pro上面,但其餘產品會先在2021年的MacBook Pro上登場。

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

線程池續:你必須要知道的線程池submit()實現原理之FutureTask!_台北網頁設計

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

前言

上一篇內容寫了Java中線程池的實現原理及源碼分析,說好的是實實在在的大滿足,想通過一篇文章讓大家對線程池有個透徹的了解,但是文章寫完總覺得還缺點什麼?

上篇文章只提到線程提交的execute()方法,並沒有講解線程提交的submit()方法,submit()有一個返回值,可以獲取線程執行的結果Future<T>,這一講就那深入學習下submit()FutureTask實現原理。

使用場景&示例

使用場景

我能想到的使用場景就是在并行計算的時候,例如一個方法中調用methodA()、methodB(),我們可以通過線程池異步去提交方法A、B,然後在主線程中獲取組裝方法A、B計算后的結果,能夠大大提升方法的吞吐量。

使用示例

/**
 * @author wangmeng
 * @date 2020/5/28 15:30
 */
public class FutureTaskTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService threadPool = Executors.newCachedThreadPool();

        System.out.println("====執行FutureTask線程任務====");
        Future<String> futureTask = threadPool.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("FutureTask執行業務邏輯");
                Thread.sleep(2000);
                System.out.println("FutureTask業務邏輯執行完畢!");
                return "歡迎關注: 一枝花算不算浪漫!";
            }
        });

        System.out.println("====執行主線程任務====");
        Thread.sleep(1000);
        boolean flag = true;
        while(flag){
            if(futureTask.isDone() && !futureTask.isCancelled()){
                System.out.println("FutureTask異步任務執行結果:" + futureTask.get());
                flag = false;
            }
        }

        threadPool.shutdown();
    }
}

上面的使用很簡單,submit()內部傳遞的實際上是個Callable接口,我們自己實現其中的call()方法,我們通過futureTask既可以獲取到具體的返回值。

submit()實現原理

submit() 是也是提交任務到線程池,只是它可以獲取任務返回結果,返回結果是通過FutureTask來實現的,先看下ThreadPoolExecutor中代碼實現:

public class ThreadPoolExecutor extends AbstractExecutorService {
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
}

public abstract class AbstractExecutorService implements ExecutorService {
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
}

提交任務還是執行execute()方法,只是task被包裝成了FutureTask ,也就是在excute()中啟動線程後會執行FutureTask.run()方法。

再來具體看下它執行的完整鏈路圖:

上圖可以看到,執行任務並返回執行結果的核心邏輯實在FutureTask中,我們以FutureTask.run/get 兩個方法為突破口,一點點剖析FutureTask的實現原理。

FutureTask源碼初探

先看下FutureTask中部分屬性:

public class FutureTask<V> implements RunnableFuture<V> {
    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

    private Callable<V> callable;
    private Object outcome;
    private volatile Thread runner;
    private volatile WaitNode waiters;
}
  1. state

當前task狀態,共有7中類型。
NEW: 當前任務尚未執行
COMPLETING: 當前任務正在結束,尚未完全結束,一種臨界狀態
NORMAL:當前任務正常結束
EXCEPTIONAL: 當前任務執行過程中發生了異常。
CANCELLED: 當前任務被取消
INTERRUPTING: 當前任務中斷中..
INTERRUPTED: 當前任務已中斷

  1. callble

用戶提交任務傳遞的Callable,自定義call方法,實現業務邏輯

  1. outcome

任務結束時,outcome保存執行結果或者異常信息。

  1. runner

當前任務被線程執行期間,保存當前任務的線程對象引用

  1. waiters

因為會有很多線程去get當前任務的結果,所以這裏使用了一種stack數據結構來保存

FutureTask.run()實現原理

我們已經知道在線程池runWorker()中最終會調用到FutureTask.run()方法中,我們就來看下它的執行原理吧:

具體代碼如下:

public class FutureTask<V> implements RunnableFuture<V> {
    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }
}

首先是判斷FutureTaskstate狀態,必須是NEW才可以繼續執行。

然後通過CAS修改runner引用為當前線程。

接着執行用戶自定義的call()方法,將返回結果設置到result中,result可能為正常返回也可能為異常信息。這裏主要是調用set()/setException()

FutureTask.set()實現原理

set()方法的實現很簡單,直接看下代碼:

public class FutureTask<V> implements RunnableFuture<V> {
    protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL);
            finishCompletion();
        }
    }
}

call()返回的數據賦值給全局變量outcome上,然後修改state狀態為NORMAL,最後調用finishCompletion()來做掛起線程的喚醒操作,這個方法等到get()後面再來講解。

FutureTask.get()實現原理

接着看下代碼:

public class FutureTask<V> implements RunnableFuture<V> {
    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }
}

如果FutureTaskstateNORMAL或者COMPLETING,說明當前任務並沒有執行完成,調用get()方法會被阻塞,具體的阻塞邏輯在awaitDone()方法:

private int awaitDone(boolean timed, long nanos) throws InterruptedException {

        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING)
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                LockSupport.park(this);
        }
    }

這個方法可以說是FutureTask中最核心的方法了,一步步來分析:

如果timed不為空,這說明指定nanos時間還未返回結果,線程就會退出。

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

q是一個WaitNode對象,是將當前引用線程封裝在一個stack數據結構中,WaitNode對象屬性如下:

 static final class WaitNode {
    volatile Thread thread;
    volatile WaitNode next;
    WaitNode() { thread = Thread.currentThread(); }
}

接着判斷當前線程是否中斷,如果中斷則拋出中斷異常。

下面就進入一輪輪的if... else if...判斷邏輯,我們還是採用分支的方式去分析。

分支一:if (s > COMPLETING) {

此時get()方法已經有結果了,無論是正常返回的結果,還是異常、中斷、取消等,此時直接返回state狀態,然後執行report()方法。

分支二:else if (s == COMPLETING)

條件成立,說明當前任務接近完成狀態,這裏讓當前線程再釋放cpu,進行下一輪搶佔cpu

分支三:else if (q == null)

第一次自旋執行,WaitNode還沒有初始化,初始化q=new WaitNode();

分支四:else if (!queued){

queued代表當前線程是否入棧,如果沒有入棧則進行入棧操作,順便將全局變量waiters指向棧頂元素。

分支五/六:LockSupport.park

如果設置了超時時間,則使用parkNanos來掛起當前線程,否則使用park()

經過這麼一輪自旋循環后,如果執行call()還沒有返回結果,那麼調用get()方法的線程都會被掛起。

被掛起的線程會等待run()返回結果后依次喚醒,具體的執行邏輯在finishCompletion()中。

最終stack結構中數據如下:

FutureTask.finishCompletion()實現原理

具體實現代碼如下:

private void finishCompletion() {
    for (WaitNode q; (q = waiters) != null;) {
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
            for (;;) {
                Thread t = q.thread;
                if (t != null) {
                    q.thread = null;
                    LockSupport.unpark(t);
                }
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null;
                q = next;
            }
            break;
        }
    }

    done();

    callable = null;
}

代碼實現很簡單,看過get()方法后,我們知道所有調用get()方法的線程,在run()還沒有返回結果前,都會保存到一個有WaitNode構成的statck數據結構中,而且每個線程都會被掛起。

這裡是遍歷waiters棧頂元素,然後依次查詢起next節點進行喚醒,喚醒后的節點接着會往後調用report()方法。

FutureTask.report()實現原理

具體代碼如下:

private V report(int s) throws ExecutionException {
    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}

這個方法很簡單,因為執行到了這裏,說明當前state狀態肯定大於COMPLETING,判斷如果是正常返回,那麼返回outcome數據。

如果state是取消狀態,拋出CancellationException異常。

如果狀態都不滿足,則說明執行中出現了差錯,直接拋出ExecutionException

FutureTask.cancel()實現原理

public boolean cancel(boolean mayInterruptIfRunning) {
    if (!(state == NEW && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally {
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}

cancel()方法的邏輯很簡單,就是修改state狀態為CANCELLED,然後調用finishCompletion()來喚醒等待的線程。

這裏如果mayInterruptIfRunning,就會先中斷當前線程,然後再去喚醒等待的線程。

總結

FutureTask的實現原理其實很簡單,每個方法基本上都畫了一個簡單的流程圖來方便立即。

後面還打算分享一個BlockingQueue相關的源碼解讀,這樣線程池也可以算是完結了。

在這之前可能會先分享一個SpringCloud常見配置代碼分析、最佳實踐等手冊,方便工作中使用,也是對之前看過的源碼一種總結。敬請期待!
歡迎關注:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

我天!xx.equals(null) 是什麼騷操作??_網頁設計公司

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

問題背景

我的天,最近做 Code Review 看到一個同事的騷操作,他寫了一個工具類,大概是這樣的:

public static boolean isNull(Object object){
    return null == object || object.equals(null);
}

判斷空,一般不是 null == object 就夠了,object.equals(null) 是什麼騷操作?

寫程序這麼多年,第一次看這樣的寫法,當時我就提出質疑了,同事拍着胸脯和我說,有個銀行的請求參數必須得這麼寫,不然就驗證不了。

我當時還在想,這是 JDK 出的什麼新類型么,覺得還是不科學,考慮去跟下同事寫的代碼,然後用他所說的情況我親自去驗證一下。

看了下,這是個老業務系統,同事用了 json-lib 這個包,歷史的江湖確實有這個包的存在,棧長之前也用過,不過後來這玩意就沒怎麼用了,現在都是 GsonJackson 的天下了。

如下面 json-lib 例子所示:

public static void main(String[] args) {
    String jsonString = "{\"name\": \"hi\",\"sex\": \"boy\", \"age\": null}";

    JSONObject jsonObject = net.sf.json.JSONObject.fromObject(jsonString);
    Object age = jsonObject.get("age");
    
    // 輸出:null
    System.out.println("age: " + age);

    // 輸出:false
    System.out.println("age == null: " + (age == null));
    
    // 輸出:true
    System.out.println("age.equals(null): " + (age.equals(null)));
}

我天!大家看到結果了吧,問題確實也如同事所說,一定要用 object.equals(null) 寫法才行,不相信結果的大家也可以親自驗證一下。

納了悶了,這樣寫,我傳一個 null 值過去不是報空指針了么?這樣寫肯定有問題,繼續深挖!

問題分析

fromObject 方法加載 JSON 串開始源碼深入分析,找到了這個神奇解析 null 值的源碼:

原來,JSON 串中的 null 值被解析成了它內部的 JSONNull 對象,然後再看下這個 JSONNull 的 equals 方法源碼:

public boolean equals(Object object) {
    return object == null || 
           object == this || 
           object == instance || 
           object instanceof JSONObject &&
           ((JSONObject)object).isNullObject() ||
           "null".equals(object);
}

問題就出在他所用的 JSON 工具類了!!!

equals 方法被重寫了……終於揭開了 object.equals(null) 的神秘面紗……

再來看下是否有新的更新包:

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

最新的版本停留在 2010 年 12 月,已經是被淘汰的東西了。

另外,json-lib 在 JDK 1.7+ 有性能影響。
推薦閱讀:請不要在 JDK 7+ 中使用這個 JSON 包了

解決方案

方法1:

換掉 object.equals(null),用 JSONNull 的實例去判斷:

public static boolean isNull(Object object){
    return null == object || JSONNull.getInstance().equals(object);
}

方法2:

換掉 json-lib 庫,用主流的 GsonJackson

具體看下這篇:Java常用的幾個Json庫,性能強勢對比,另外 FastJson 也不建議用了,漏洞比較多。

這個由於是老系統,太多業務使用了這個庫,換掉的開發、測試成本和風險比較大,暫時考慮先用方案1先解決這個問題。

關注Java技術棧微信公眾號,棧長將繼續分享好玩的 Java 技術,公眾號第一時間推送,在公眾號後台回復:Java,可以獲取歷史 Java 教程,都是乾貨。

推薦去我的博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、後端、架構、阿里巴巴等大廠最新面試題

覺得不錯,別忘了點贊+轉發哦!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

手把手教你學numpy,從此數據處理不再慌【三】_網頁設計

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

本文始發於個人公眾號:TechFlow,原創不易,求個關注

今天是numpy專題的第三篇,我們來聊聊numpy當中的索引。

上篇的末尾其實我們簡單地提到了索引,但是沒有過多深入。沒有過多深入的原因也很簡單,因為numpy當中關於索引的用法實在是很多,並不是我們想的那樣用一個下標去獲取數據就完事了。

所以我整理了一下相關的用法,把關於索引的使用簡單分成了幾類,我們一個一個來看。

切片索引

切片我們都熟悉,用冒號將兩個數隔開,表示一個區間的上界和下界。通過這種方式訪問這個區間內的所有元素。

這一點我們之前介紹過,我們簡單回顧一下。

這是一維數組的切片,既然一維數組可以切片,那麼同樣高維數組也可以切片。我們來看一個二維的數組的切片:

我們生成了一個3 x 4的二維數組,然後通過切片獲取了它的1-2數據。由於我們是對行切片,默認保留這一行的所有數據。

如果我們並不需要所有數據,而是只需要某一列的固定數據,可以寫成這樣:

這一行代碼的意思是對於行我們獲取1-3行固定第二列的數據,我們用表格表示的話大概是下面這個樣子:

我們也可以對兩個維度同時切片,這樣可以得到更加複雜的數據:

這樣切片獲得的數據大概是這樣的:

也就是說在numpy的數組當中各個維度是分開的,每一個維度都支持切片。我們可以根據我們的需要切片或者是固定下標來獲取我們想要的切片。

bool型索引

numpy當中還有一個非常好用的索引方式叫做bool型索引。前文介紹廣播的時候曾經介紹過,當我們將兩個大小不一致的數組進行計算的時候,numpy會自動幫我們將它們廣播成大小一致的情況再進行運算。

而邏輯判斷其實也是一種運算,所以如果我們將邏輯運算應用在numpy數組上的話同樣會得到一個numpy數組,只不過是bool類型的numpy數組。

我們來看一個例子:

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

我們創建了一個numpy的數組,然後將它和整數4進行比較,numpy會將這個運算廣播到其中每一個元素當中,然後返回得到一個bool類型的numpy數組。

這個bool類型的數組可以作為索引,傳入另外一個數組當中,只有bool值為true的行才會被保留。

我們發現只有第4行和第6行的數據被保留了,也就是bool值為true的行號被保留了。這是非常有用的數據獲取方式,我們可以直接將判斷條件放入索引當中進行數據的過濾,如果應用熟練了會非常方便。

再舉個例子,假如我們要根據二維數據的第一列的數據進行過濾,僅僅保留第一列數據大於0.5的。如果按照傳統的方法我們需要用一個循環去過濾,但是使用bool類型索引,我們可以只需要一行搞定:

arr[arr[:, 0] > 0.5]

如果有多個條件,我們可以用位運算的與或非進行連接。在Python當中位運算的與或非分別用符號&, |, ~表示。

舉個例子,比如我們想要篩選出arr數組當中第1列大於0.5,並且第二列小於0.5的數據,我們可以寫成這樣:

arr[(arr[:, 0] > 0.5) & (arr[:, 1] < 0.5)]

如果我們想求這個條件的相反條件,我們當然可以將判斷條件反過來寫,但是也可以通過~符號直接取反:

arr[~((arr[:, 0] > 0.5) & (arr[:, 1] < 0.5))]

花式索引

除了bool索引之外,numpy當中還支持一種花式索引。

所謂的花式索引,意思是說支持將另外一個數組當做是索引來訪問數據

舉個很簡單的例子:

從上面的例子我們可以看出來,我們把idx這個數組當中的值當做了索引進行了數據的訪問。並且有重複值也沒有關係,numpy不會進行去重。

通過數組訪問數據有什麼用呢?其實非常有用,在我們做機器學習的過程當中,我們經常涉及到一個採樣的問題。我們每次訓練並不是全量的數據,否則非常慢,有時候甚至是不可能完成的,因為數據量太大了。我們往往是抽取出一批數據作為一個batch來訓練的,這個在之前批量梯度下降的文章當中曾經提到過。

那麼一個batch的數據是怎麼抽取的呢?就是這樣抽取的,我們會調用np中的一個函數叫做choice,我們用它來從所有樣本的下標當中抽取我們指定數量的下標。

有了下標數組之後,我們用一下花式索引就可以拿到對應的全部數據了,如果你看過大牛寫的深度學習的代碼,裏面幾乎都是這樣實現的。

總結

今天關於numpy當中索引的使用和介紹就到這裏,僅僅看介紹可能感受並不明顯。但如果上手用numpy做過一次數據處理和實現過機器學習的模型,相信一定可以感受到它的易用性和強大的功能。索引這個功能非常常用,也非常重要,在後序的pandas庫當中同樣沿用了numpy中對於索引的設定和功能。因此這既是重要的基本功,也是為後面的學習打基礎。

如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

環境減災二號01組A、B星成功發射!環境衛星家族又添新成員_租車

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

2020-09-30

2020-09-30
分享到:
[打印]
字號:[大] [中] [小]   9月27日11時23分,我國在太原衛星發射中心用長征四號乙運載火箭,以一箭雙星方式成功發射環境減災二號01組A、B星。
  環境減災二號01組A、B星是國家民用空間基礎設施中長期發展規劃(2015-2025年)支持立項,由生態環境部與應急管理部共同牽頭研製建設的光學對地遙感衛星,用於接替已在軌運行12年的環境減災一號A、B衛星,可滿足國家生態環境部、應急管理部應用需求,併兼顧國土資源、水利、農業、林業、地震等行業需求。 環境減災二號01組A、B星搭載長征四號乙火箭點火起飛   環境減災二號01組A、B星採用了太陽同步回歸軌道,兩顆衛星技術狀態相同,設計壽命為5年,每顆衛星配置了4類光學載荷,包括16m相機、高光譜成像儀、紅外相機、大氣校正儀。其中,16m相機載荷由四台可見光CCD相機組成,通過視場拼接可提供幅寬為800km的多光譜圖像;高光譜成像儀幅寬為96km;紅外相機幅寬為720km;大氣校正儀可在軌同步獲取與16m相機同視場的大氣多譜段信息,進行大氣輻射校正。 環境減災二號01組A、B星載荷配置示意圖 環境減災二號01組A、B星拍攝示意圖   環境減災二號01組A、B星發射成功后可實現同軌組網觀測,

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

大幅提高我國中分辨率可見光、紅外及高光譜遙感數據獲取能力,滿足區域生態、環境空氣、地表水環境、城市環境、環境災害、全球環境變化等大範圍、全天候、全天時、動態的監測與評估的遙感數據需要,為實現科學治污、精準治污、依法治污提供重要技術支撐,使我國生態環境監測治理能力更加科學化、現代化。 雙星同軌組網觀測示意圖   環境減災二號01組A、B星成功發射,對提升生態環境遙感監測業務化能力極為重要。在大氣環境遙感監測方面,可針對秸稈焚燒和沙塵污染進行遙感動態監測,實現大氣環境污染的遙感精細化監測應用,為大氣污染防治以及空氣環境質量預警預報提供技術支持;在水環境遙感監測方面,可對恭弘=叶 恭弘綠素a、懸浮物等水質參數,溢油、赤潮等近海環境事件,核電廠、火電廠溫排水等水體熱污染開展動態監測;在生態環境監測方面,可為生態系統監測與評估、生態環境關鍵參數生產、自然保護區綜合監管、礦產資源開發監測評估和城市群生態環境監測等生態管理核心業務提供重要數據支撐,實現生態環境信息提取、分析和綜合應用的業務化運行。 衛星研製團隊部分成員與衛星合影   環境減災二號衛星在為生態環境保護等多個領域提供服務的同時,也將不斷在衛星觀測精度、空間分辨率和時間分辨率等方面繼續提升能力。待“十四五”期間環境減災“4+4”衛星星座建成后,將形成全天時、全天候、動態實時的中分辨率全球生態環境監測能力,為實現“高精度、全方位、短周期”的生態環境遙感監測目標提供更為強力的支撐。

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

Telegraf和Grafana監控多平台上的SQL Server_如何寫文案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

問題

SQL Server在很多企業中部署在多個平台上(Windows,Linux和Container),需要一種能支持多平台的解決方案用於收集和展示相關的監控指標。

我選擇企業中比較流行的監控展示工具Grafana和監控指標收集工具Telegraf進行實現。這也是為了方便與企業中已經在存在監控平台進行整合和對接。

如上圖所示,Telegraf部署在SQL所在host,收集數據發送給時序數據庫Influxdb存儲,然後Grafana用於展示數據。

解決方案

  • 安裝和配置InfluxDB

我將InfluxDB和Grafana安裝在同一台CentOS主機上,生產環境中最好是分開。

# 下載1.8的stable version後進行安裝
wget https://dl.influxdata.com/influxdb/releases/influxdb-1.8.0.x86_64.rpm
chmod 755 influxdb-1.8.0.x86_64.rpm
yum localinstall influxdb-1.8.0.x86_64.rpm

# 啟動並設置自啟動
systemctl start influxdb
systemctl enable influxdb

# 8086用於客戶端的HTTP連接,8088用於CLI調用RPC進行備份和還原操作
firewall-cmd --zone=public --add-port=8086/tcp --permanent
firewall-cmd --zone=public --add-port=8088/tcp --permanent
firewall-cmd --reload

# 連接到influxdb並創建用戶
fluxdb
> CREATE USER admin WITH PASSWORD '<password>' WITH ALL PRIVILEGES

# 啟用http用戶驗證,修改influxdb.conf中http section中auth-enabled = true
vim /etc/influxdb/influxdb.conf
systemctl restart influxdb

# 創建用於存儲監控數據的數據庫,保存6個月的數據
influx -username 'admin' -password '<password>'
> CREATE DATABASE telegraf
> CREATE RETENTION POLICY telegraf_6m ON telegraf DURATION 180d REPLICATION 1 DEFAULT
> SHOW DATABASES
  • 安裝和配置Grafana

# 下載並安裝Grafana
wget https://dl.grafana.com/oss/release/grafana-7.0.1-1.x86_64.rpm
chmod 775 grafana-7.0.1-1.x86_64.rpm
yum localinstall grafana-7.0.1-1.x86_64.rpm

# 設置自啟動
systemctl start grafana-server.service
systemctl enable grafana-server.service

# 允許Grafana默認的端口3000
firewall-cmd --zone=public --add-port=3000/tcp --permanent
firewall-cmd --reload

然後在Browser中訪問http:// :3000,第一次訪問時默登錄認賬號和密碼都為admin,登錄後會提示修改密碼。

  • 在客戶端主機安裝和配置Telegraf

所謂客戶端,就是SQL所在主機

Telegraf連接到SQL,需要一個login,具有 VIEW SERVER STATE and VIEW ANY DEFINITION的權限,所以在每個被監控的實例上都需要創建之。

USE master;
GO
CREATE LOGIN [telegraf] WITH PASSWORD = N'1qaz@WSX';
GO
GRANT VIEW SERVER STATE TO [telegraf];
GO
GRANT VIEW ANY DEFINITION TO [telegraf];
GO
  • Telegraf on Linux
wget https://dl.influxdata.com/telegraf/releases/telegraf-1.14.3-1.x86_64.rpm
sudo yum localinstall telegraf-1.14.3-1.x86_64.rpm 

安裝完成后,先要修改Telegraf的配置文件,再啟動。在配置文件中主要配置兩個部分:inputs和outputs。 inputs表示監控數據從哪裡來,outputs表示監控要發送到哪裡去。

打開/etc/telegraf/telegraf.conf,找到[[outputs.influxdb]]部分,所有配置項默認都被註釋了。我們需要刪除註釋並配置一些項。主要是Influxdb的地址,用戶名、密碼和數據庫名等。

[[outputs.influxdb]]
  ## The full HTTP or UDP URL for your InfluxDB instance.
  ##
  ## Multiple URLs can be specified for a single cluster, only ONE of the
  ## urls will be written to each interval.
  # urls = ["unix:///var/run/influxdb.sock"]
  # urls = ["udp://127.0.0.1:8089"]
  urls = ["http://172.17.2.4:8086"]

  ## The target database for metrics; will be created as needed.
  ## For UDP url endpoint database needs to be configured on server side.
  database = "telegraf"

  ## The value of this tag will be used to determine the database.  If this
  ## tag is not set the 'database' option is used as the default.
  # database_tag = ""

  ## If true, the 'database_tag' will not be included in the written metric.
  # exclude_database_tag = false

  ## If true, no CREATE DATABASE queries will be sent.  Set to true when using
  ## Telegraf with a user without permissions to create databases or when the
  ## database already exists.
  skip_database_creation = true

  ## Name of existing retention policy to write to.  Empty string writes to
  ## the default retention policy.  Only takes effect when using HTTP.
  retention_policy = ""

  ## The value of this tag will be used to determine the retention policy.  If this
  ## tag is not set the 'retention_policy' option is used as the default.
  # retention_policy_tag = ""

  ## If true, the 'retention_policy_tag' will not be included in the written metric.
  # exclude_retention_policy_tag = false

  ## Write consistency (clusters only), can be: "any", "one", "quorum", "all".
  ## Only takes effect when using HTTP.
  write_consistency = "any"

  ## Timeout for HTTP messages.
  timeout = "5s"

  ## HTTP Basic Auth
  username = "admin"
  password = "<password>"
  • 找到[[inputs.sqlserver]]部分,取消相關配置項的註釋,servers部分連接到本地實例。

Telegraf默認的Plugin中包括了對SQL Server的實現, 這個Plugin還包括了對Azure SQL PaaS的實現

# # Read metrics from Microsoft SQL Server
 [[inputs.sqlserver]]
#   ## Specify instances to monitor with a list of connection strings.
#   ## All connection parameters are optional.
#   ## By default, the host is localhost, listening on default port, TCP 1433.
#   ##   for Windows, the user is the currently running AD user (SSO).
#   ##   See https://github.com/denisenkom/go-mssqldb for detailed connection
#   ##   parameters, in particular, tls connections can be created like so:
#   ##   "encrypt=true;certificate=<cert>;hostNameInCertificate=<SqlServer host fqdn>"
        servers = [
                        "Server=localhost;Port=1433;User Id=telegraf;Password=<yourPassword>;app name=telegraf;log=1;"
                ]
#
#   ## Optional parameter, setting this to 2 will use a new version
#   ## of the collection queries that break compatibility with the original
#   ## dashboards.
        query_version = 2
#
#   ## If you are using AzureDB, setting this to true will gather resource utilization metrics
#   # azuredb = false
#
#   ## Possible queries:
#   ## - PerformanceCounters
#   ## - WaitStatsCategorized
#   ## - DatabaseIO
#   ## - DatabaseProperties
#   ## - CPUHistory
#   ## - DatabaseSize
#   ## - DatabaseStats
#   ## - MemoryClerk
#   ## - VolumeSpace
#   ## - PerformanceMetrics
#   ## - Schedulers
#   ## - AzureDBResourceStats
#   ## - AzureDBResourceGovernance
#   ## - SqlRequests
#   ## - ServerProperties
#   ## A list of queries to include. If not specified, all the above listed queries are used.
#   # include_query = []
#
#   ## A list of queries to explicitly ignore.
#   exclude_query = [ 'Schedulers' , 'SqlRequests']

啟動Telegraf之後,可以看到時已經加載的inputs和收集間隔

※教你寫出一流的銷售文案?

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

[root@SQL19N1 log]# systemctl status telegraf      
● telegraf.service - The plugin-driven server agent for reporting metrics into InfluxDB
   Loaded: loaded (/usr/lib/systemd/system/telegraf.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2020-05-26 14:19:07 UTC; 19min ago
     Docs: https://github.com/influxdata/telegraf
 Main PID: 12359 (telegraf)
   CGroup: /system.slice/telegraf.service
           └─12359 /usr/bin/telegraf -config /etc/telegraf/telegraf.conf -config-directory /etc/telegraf/telegraf.d

May 26 14:19:07 SQL19N1 systemd[1]: Started The plugin-driven server agent for reporting metrics into InfluxDB.
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! Starting Telegraf 1.14.3
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! Loaded inputs: system cpu disk diskio kernel mem processes swap sqlserver
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! Loaded aggregators:
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! Loaded processors:
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! Loaded outputs: influxdb
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! Tags enabled: host=SQL19N1
May 26 14:19:07 SQL19N1 telegraf[12359]: 2020-05-26T14:19:07Z I! [agent] Config: Interval:20s, Quiet:false, Hostname:"SQL19N1", Flush Interval:10s
  • Telegraf on Windows

以管理員身份執行如下PowerShell命令

# 下載軟件
wget https://dl.influxdata.com/telegraf/releases/telegraf-1.14.3_windows_amd64.zip ·
    -OutFile "c:\temp\telegraf-1.14.3_windows_amd64.zip"

# 解壓縮到C:\Program Files\Telegraf
Expand-Archive "c:\temp\telegraf-1.14.3_windows_amd64.zip", "C:\Program Files"

# 將telegraf安裝為windows服務
C:\"Program Files"\Telegraf\telegraf.exe --service install

修改telegraf.conf中outputs.influxdb和添加inputs.sqlserver部分,這些內容和在Linux上的配置一樣,就不贅述了。

conf修改完成后,可以先測試一下telegraf是否能正常啟動,沒問題的話就啟動telegraf服務。

# 測試
C:\"Program Files"\Telegraf\telegraf.exe --config C:\"Program Files"\Telegraf\telegraf.conf --test

# 啟動服務
C:\"Program Files"\Telegraf\telegraf.exe --service start
  • 配置Grafana的數據源和Dashboard

登錄Grafana后,在左側的Configuration->Data Source中配置InfluxDB數據源,填寫地址、賬號、密碼並設置為默認數據源,如下圖

Dashboard,可以自己創建,也可以在採用公開社區的(感謝熱心無私的大佬們)。這裏,我採用SQL Servers by Jonathan Rioux。這個Dashboard中使用的Piechart不是Grafana預置的,所以還需要安裝:

# Grafana所在Host安裝,重啟服務生效
grafana-cli plugins install grafana-piechart-panel
systemctl restart grafana-server.service

然後在Grafana界面,選擇左側的Dashboard->Import->填入Dashboard ID->Import,如下圖:

配置完成后的,可以看這個Dashboard提供的信息還比較豐富的,您也可以根據自己的需要修改和添加相關內容.

總結

  • 實際情況中,自帶的數據收集和報表不能完全滿足業務需求,自定義的數據收集和自定義的Dashboard,也是非常容易實現的,下次再寫

  • 如果已經在使用Zabbix了,Grafana可以直接對接到Zabbix的數據輸出。

  • Telegraf能非常好的支持Cloud環境,下次說說對Azure SQL PaaS的監控

  • 本文內容僅代表個人觀點,與任何公司和組織無關

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※別再煩惱如何寫文案,掌握八大原則!

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

小心 HttpClient 中 FormUrlEncodeContent 的 bug_網頁設計公司

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

小心 HttpClient 中 FormUrlEncodeContent 的 bug

Intro

最近發現活動室預約項目里的上傳圖片有時候會有問題,周末找時間測試了一下,發現小圖片的上傳沒問題,大圖片上傳會有問題,而且異常信息還很奇怪,System.UriFormatException: Invalid URI: The Uri string is too long 看這個錯誤的信息還以為是請求的 url 過長導致的,但是實際請求的 url 很短,詭異的異常信息

測試示例

為了方便大家了解和測試這個bug,我在 Github 上提供了一個示例 https://github.com/WeihanLi/SamplesInPractice/blob/master/HttpClientTest/FormUrlEncodeContentTest.cs

HttpClient 示例代碼:

public class FormUrlEncodeContentTest
{
    private const string TestUrl = "https://cnblogs.com";

    public static async Task FormUrlEncodedContentLengthTest()
    {
        using (var httpClient = new HttpClient(new NoProxyHttpClientHandler()))
        {
            using (var response = await httpClient.PostAsync(TestUrl, new FormUrlEncodedContent(new Dictionary<string, string>()
            {
                {"bigContent", new string('a', 65535)},
            })))
            {
                Console.WriteLine($"response status code:{response.StatusCode}");
            }
        }
    }

    public static async Task ByteArrayContentLengthTest()
    {
        using (var httpClient = new HttpClient(new NoProxyHttpClientHandler()))
        {
            var postContent = $"bigContent={new string('a', 65535)}";
            using (var response = await httpClient.PostAsync(TestUrl, new ByteArrayContent(postContent.GetBytes())))
            {
                Console.WriteLine($"response status code:{response.StatusCode}");
            }
        }
    }

    public static async Task StringContentLengthTest()
    {
        using (var httpClient = new HttpClient(new NoProxyHttpClientHandler()))
        {
            var postContent = $"bigContent={new string('a', 65535)}";
            using (var response = await httpClient.PostAsync(TestUrl, new StringContent(postContent)))
            {
                Console.WriteLine($"response status code:{response.StatusCode}");
            }
        }
    }
}

測試代碼:

InvokeHelper.OnInvokeException = Console.WriteLine;

await InvokeHelper.TryInvokeAsync(FormUrlEncodeContentTest.FormUrlEncodedContentLengthTest);
Console.WriteLine();
await InvokeHelper.TryInvokeAsync(FormUrlEncodeContentTest.StringContentLengthTest);
Console.WriteLine();
await InvokeHelper.TryInvokeAsync(FormUrlEncodeContentTest.ByteArrayContentLengthTest);

Console.WriteLine("Completed!");

輸出結果如下:

揪出異常始末

上傳圖片的時候會調用一個碼雲的一個 POST 接口來保存上傳的圖片,參數是通過 form-data 的方式傳遞的,在 POST 的時候報異常了,異常信息很詭異,具體信息和上面的是一樣的:

這個異常信息看上去像是 url 過長導致的,但是實際的 url 很短只有幾百,而且從調用的堆棧上來看是 FormUrlEncodedContent 的 bug,然後根據異常堆棧信息去看了一下源碼,部分源碼如下:

首先看 FormUrlEncodedContent 做了什麼:

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

然後再找上一層堆棧信息,Uri是一個分部類(partial),你如果直接在 Github 上 Find 的話會找到多個 Uri 相關的文件,最後在 UriExt 中找到了上面的 EscapeDataString 方法:

最後來看最上層的堆棧信息 UriHelper.EsacpeString 方法,找到異常拋出的地方

在 Uri 這個類中可以找到上面定義的 c_MaxUriBufferSize,它的值是 0xFFF0 轉成十進制就是 65520

找到問題所在之後,就可以避免這個問題了,再遇到這個問題也就知道是怎麼回事了,上面的問題就是 post 的數據太大了,超過了這個限制,所以引發的異常

More

既然知道這個是 FormUrlEncodedContent 的 bug,那麼修復它就可以通過避免使用它,可以直接使用 ByteArray Content,或者不需要 Encode 處理直接用 StringContent 也是可以的

後來在 Github 搜 issue 的時候發現也有很多人遇到了這個問題,這個問題會在 net5 中得到修復,詳見 PR https://github.com/dotnet/corefx/pull/41686

文中一些源碼的鏈接在文章最後的 Reference 的部分可以找到

Reference

  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Net.Http/src/System/Net/Http/FormUrlEncodedContent.cs#L53
  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Private.Uri/src/System/UriExt.cs#L597
  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Private.Uri/src/System/UriHelper.cs#L134
  • https://github.com/dotnet/corefx/blob/release/3.1/src/System.Private.Uri/src/System/Uri.cs
  • https://github.com/dotnet/corefx/pull/41686
  • https://github.com/dotnet/corefx/tree/release/3.1
  • https://github.com/WeihanLi/SamplesInPractice/blob/master/HttpClientTest/Program.cs
  • https://github.com/OpenReservation/ReservationServer/commit/0262b2a6ce20c3ec12acc9548235757c18b20690#diff-dd926ccf347a255671a64f9e3edd5a88

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊