Clef 讓你登入 WordPress 網站免輸入帳號密碼,全新兩步驟驗證自動登入超安全!

本文章介紹的 Clef 外掛程式僅適用於以 WordPress 自架網站的使用者,若你是使用 WordPress.com 提供的免費網誌服務則無法安裝。

之前我曾經利用一些篇幅來針對 WordPress 架設的網站安全提供建議,例如 9 個提升 WordPress 網站安全性的方法、或者是安裝 WordPress 後你應該要做的 25 件事,如果你也是使用 WordPress 架站的話,請一定要對這些細節特別用心,因為任何一點微小的疏失,都可能成為未來被有心人士入侵或破壞的漏洞。

若你對於網站安全特別重視,一定不難發現,上面的兩篇文章裡提到許多關於帳號密碼和登入的細節。就 Pseric 的經驗來說,設定一組難以被猜測出來的帳號密碼,搭配上 Google Authenticator 之類的兩步驟驗證外掛,在帳號密碼以外多一道防護其實就能大幅提昇安全性。

最近我又發現一款全新的安全防護工具 Clef,簡單來說,它是帳號密碼、兩步驟驗證以外的另一種選擇,使用者無須輸入難以記憶的密碼組合,也不用等待手機來產生兩步驟驗證隨機代碼,利用手機上的 Clef 應用程式對著登入畫面的條碼一掃,直接驗證身份登入。

Clef 將安全驗證的複雜過程交給使用者最貼身的配備,也就是手機或行動裝置,讓驗證變得更快、更簡單。目前已經支援 iOS、Android 兩大平台。

Clef Two-Factor Authentication 雖然名稱上是兩步驟驗證,但它其實跟我們熟悉產生驗證碼方式有些微不同,Clef 會在畫面產生類似於條碼的波浪狀驗證碼(Wave),利用身份驗證後的 Clef 手機應用程式,以鏡頭對著電腦上的驗證碼一掃,就能夠確認你的身份並完成登入的程序。

外掛名稱:Clef Two-Factor Authentication
外掛鏈結:https://wordpress.org/plugins/wpclef/

使用教學

STEP 1

使用 Clef 完全不需要用到帳號密碼,減少密碼在傳輸過程中被擷取而造成安全問題的可能性。不僅如此,Clef 還能將 WordPress 原有的帳號密碼登入驗證方式停用,以 Clef 取代傳統登入表單(新的登入畫面會如同下圖)。

STEP 2

要安裝這個功能非常簡單。首先,你要有一支 iPhone 或 Android 手機、平板電腦,因為每次登入都會用到,請先在手機或平板電腦上安裝 Clef 應用程式(可以在 Clef 官方網站找到下載鏈結),安裝後先放著,我們要先進行 WordPress 端的設定。

開啟、登入你的 WordPress 網站後,點選左側選單的「外掛」->「安裝外掛」,然後搜尋「Clef」即可找到這個外掛功能,點選右上角的「立刻安裝」把它安裝到網站。

STEP 3

下載、啟用外掛功能後,第一次使用需要進行設定。點選外掛的「Get Started」開始進行初次使用設定。

STEP 4

如果你還沒有下載 Clef App 的話,在開始前也會提示使用者先下載,把 Clef 安裝到自己的手機才能繼續。若已安裝完成,點選「I already have the app」繼續下一步。

接著畫面上會出現 Clef Wave,也就是波浪狀的驗證碼,拿出你的手機或平板電腦,打開剛才下載的 Clef 應用程式,對著螢幕上的驗證碼掃描。完成這步驟後,就能讓你的網站與手機 Clef 進行連結。

STEP 5

接下來會跳轉到一個隨機的 clef.io 鏈結,看到箭頭了嗎?請依照指示,選擇在畫面上出現的網址(在你的手機上進行選擇),這個步驟是 Clef 後來再加入的額外驗證,目的是避免不小心被其他人掃描、登入,多一層驗證的防護措施。

STEP 6

在結束 Clef 外掛設定前,可以選擇是否邀請其他使用者來使用 Clef,可以點選藍色按鈕來發送邀請,或者點選「Continue and finish setup」完成設定。

STEP 7

順帶一提,如果你想用 Clef 驗證方式來取代 WordPress 傳統帳號密碼登入框,可以在外掛設定的「Disable Passwords」將相關功能關閉。若你使用 WordPress App 或離線編輯器,必須要透過 API 驗證身份,也記得把 Allow passwords for API 功能打開才能正常連線。

值得一試的三個理由:

  1. 以全新的驗證波浪(Clef Wave)取代原有的帳號密碼登入
  2. 支援 iOS、Android,掃描即可快速驗證身份
  3. 可設定自動登出時間,或從遠端登出帳號
  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

TinyPNG 也有 WordPress 圖片壓縮外掛,上傳後自動最佳化(Compress JPEG & PNG images)

本文章介紹的 Compress JPEG & PNG images 外掛程式僅適用於 WordPress 自架網站的使用者,若你是使用 WordPress.com 免費網誌服務則無法安裝。

TinyPNG 是我個人相當喜愛的圖片壓縮工具,後來推出 TinyJPG 後,使它原先支援的格式除了 PNG 外又多了一項 JPG,對於大部分使用者來說已經相當夠用,可惜先前它並沒有針對 WordPress 推出外掛功能,要壓縮圖片都必須手動上傳,然後再把壓縮好的圖片下載插入文章裡,雖然這麼做不會花太多時間,但如果能夠跟 WordPress 整合那就更方便了!

一直以來,WordPress 都沒有很好用的圖片壓縮外掛,也就只能勉強使用 WP Smush 這款很老牌的外掛工具,但它的壓縮效果、速度並不是很理想。

今年二月 TinyPNG 終於推出了官方版的 WordPress 外掛,現在使用者可以免費下載、將 TinyPNG 安裝到自己的網站,利用它自動壓縮、最佳化上傳的圖片特性,大幅減少圖片佔用的空間,同時也能提升網站圖片載入速度,尤其在 Google 將網站開啟速度列為搜尋排名的參考因素後,壓縮圖片對於搜尋引擎最佳化(SEO)來說有正面的影響。

這款名為 Compress JPEG & PNG images 的圖片壓縮外掛來自 TinyPNG,利用 API 串連的功能,讓你的 WordPress 媒體庫可以直接使用 TinyPNG 技術來壓縮圖片,免費方案每個月可以免費壓縮 500 張圖片,超過才會開始計價收費,對一般網站來說,每月 500 張的配額其實已經相當夠用。

外掛名稱:Compress JPEG & PNG images
外掛鏈結:https://wordpress.org/plugins/tiny-compress-images/

使用教學

STEP 1

開啟你的 WordPress 控制台,點選左側選單的「外掛」->「安裝外掛」,在右上角的搜尋框輸入「tinypng」,可以找到本文介紹的「Compress JPEG & PNG images」外掛,點選右上角的「立刻安裝」就能從 WordPress 官方資料庫下載、安裝這個外掛功能。

STEP 2

安裝後,點選「啟用外掛」來開啟這項功能。

STEP 3

接著從「設定」裡找到「媒體」功能,將頁面往下拉,會有一個 TinyPNG API Key 欄位需要設定,第一次使用請先點選下方的 TinyPNG Developer section 來申請 API 金鑰。

此外,預設情況下,TinyPNG 會針對原圖、縮圖、中型尺寸、大型尺寸等圖片格式進行最佳化處理,若你沒有用到其他格式的圖片,建議可以只勾選「Original」原始尺寸即可。

STEP 4

開啟 TinyPNG Developer API 頁面,在上方藍色欄位填入你的姓名、Email,點選右邊的 Get your API key 按鈕後,就能立即收到一封 TinyPNG 郵件,點選信中的鏈結開啟,即可找到你的 API 金鑰。

回到上一個畫面,把 API key 貼上,儲存後就能啟用 WordPress 外掛內的圖片壓縮功能。

STEP 5

在安裝完 Compress JPEG & PNG images 後,每次上傳圖片至媒體庫時,就會透過 TinyPNG 全自動進行壓縮,你再也不用手動開啟 TinyPNG 網站然後上傳、壓縮圖片。

如果你網站之前已經有許多圖片,可以透過「工具」->「Compress All Images」功能來批次自動壓縮、最佳化網站內的所有圖片,不過要注意如果超過五百張圖片,必須回 TinyPNG 網站輸入你的信用卡資料,才能夠繼續壓縮,因為每月的免費額度為 500 張。

STEP 6

點選 Compress All Images 後,就會對網站媒體庫內的圖片進行自動壓縮、上傳,不過記得要把網站分頁開著,若是跳出頁面,壓縮工具就會暫停。

若你有大量需求,TinyPNG 在超過 500 張圖片後才會開始計費,每張圖片 $0.009 美元,若單月超過一萬張圖片,價格會壓低至 $0.002 美元,若拿來交換速度、頻寬跟 CDN 開銷那其實是很划算的投資,如有需要的話不妨參考一下。

值得一試的三個理由:

  1. 利用 TinyPNG 技術壓縮、最佳化網站圖片
  2. 搭配 WordPress 外掛可以自動對圖片進行壓縮處理
  3. 內建批次壓縮工具,可一鍵處理媒體庫內的所有圖片
  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

啟用 Jetpack「單一登入」機制教學,讓你的 WordPress 網站更安全(含兩步驟驗證)

好像有一段時間沒有寫關於 WordPress 架站的相關文章,事實上,最近找到一個能夠有效提升 WordPress 安全性的方法,簡單來說,啟用內建於 Jetpack 外掛的「單一登入」模組,也就是 Single Sign On(SSO)功能,然後把原本帳號密碼驗證方式關閉停用,將驗證導回讓 WordPress.com 處理。

這麼做有那些好處呢?除了可為帳號加上兩階段驗證保護,從應用程式或手機來接受驗證碼,提高帳號安全性以外,更大的優點是自己的網站無須負載被暴力攻擊、破解的資源耗費問題,因為驗證會被導向 WordPress.com,這個由 Automattic 營運的平台將提供更好的安全性防護。

使用 WordPress 架站的話一定知道:WordPress 登入畫面預設是對外開放的,這也表示任何人都可以存取你的登入頁面,甚至可能從其他地方取得密碼並登入網站。為了更好的安全性,建議要妥善保護好登入頁面(延伸閱讀:安裝 WordPress 後你應該做的 25 件事、9 個提升 WordPress 網站安全性的方法)。

不過,現在不用這麼麻煩了!因為 Jetpack 的 Single Sign On(SSO)把登入驗證的任務交給 WordPress.com 為你把關,拋棄那些第三方登入、兩階段驗證的相關外掛吧!照著接下來的教學,我會教你如何快速有效提升網站的登入頁面安全性。

使用「單一登入」功能保護你的 WordPress

WordPress 的「單一登入(SSO)」功能提供了一個更安全的驗證方法,以保護你的網站免於受到暴力破解攻擊。一旦啟用,你原有的 WordPress 登入畫面會被關閉,你必須登入 WordPress.com 帳號才能進入自己的 WordPress 網站控制台。

Digital Inspiration 在這篇文章提到開啟「單一登入」有這些好處:

  1. 由於 WordPress.com 已經支援兩階段驗證,現在啟用後將能為你的網站提供相同等級的安全防護機制,而且不需要安裝額外的外掛功能。
  2. 你網站所有登入請求,包括惡意登入嘗試,現在都會被導向 WordPress.com,進而減少伺服器和資料庫的負載。
  3. 如果你管理多個網站,你可以使用單一 WordPress.com 帳戶來登入、管理,無須記住多組不同的帳號密碼組合。

如何使用 Jetpack 實現「單一登入」?

STEP 1

如果你從來沒用過 Jetpack 外掛,那麼你可能也沒有 WordPress.com 帳戶,可以先開啟這個鏈結,填入 Email、使用者名稱、密碼等相關資訊來建立一個 WP.com 帳號。在註冊時你可能會被要求建立一個 WordPress 網誌,但這不會影響接下來的操作。

STEP 2

申請好 WordPress.com 帳號後,開啟這個鏈結,為你的帳號設定「兩步驟驗證」,增添額外的安全防護。設定前要先填入自己的手機號碼,下載兩階段驗證專用的手機應用程式,跟著網頁步驟操作即可完成設定。

延伸閱讀:

  • 8 個線上服務「兩步驟驗證」設定說明,確保帳戶免於威脅

一旦啟用你的 WordPress.com 兩步驟驗證後,未來當你登入帳號時不僅要輸入正確的使用者名稱、密碼,同時也要輸入一組由行動裝置產生的驗證碼。

STEP 3

回到你的 WordPress 網站,從「外掛 | 安裝外掛」頁面找到 Jetpack,點選「立刻安裝」來自動下載、安裝到你的網站。

第一次使用 Jetpack 時會要求連接到你的 WordPress.com 帳戶,按下連接、登入帳號後,點選「Approve」藍色按鈕即可把網站與你的帳號連結。

STEP 4

設定好 Jetpack 後,即可開啟相關模組功能(在 Jetpack 3.8 版時出現一個問題,那就是介面會變成英文版,不過不影響使用)。

找到我們需要的「單一登入(英文為 Single Sign On)」,然後將它啟用。

STEP 5

以 FTP、SFTP 或 SSH 連接到你的 WordPress 伺服器,開啟當前使用的佈景主題資料夾(路徑為 wp-content/themes/theme-name),編輯 functions.php 檔。複製以下程式碼,貼到檔案後儲存:

add_filter( 'jetpack_sso_bypass_login_forward_wpcom', '__return_true' );

這個步驟主要用於「停用 WordPress 內建的登入頁面」,改由重新導向至 WordPress.com 進行登入及驗證身份。如果你的網誌是屬於多人協作,或者你希望保留原有的登入畫面,可跳過此步驟。

STEP 6

前往「帳號 | 個人資訊」頁面,可以在最底部找到「Log in with WordPress.com」按鈕,這是用來把你的網站登入帳號連結 WordPress.com 帳號。登入後,你就能看到如下畫面,表示已成功連結(Connected)至這個帳號,同時也啟用了兩步驟驗證。

STEP 7

最後,當你登出、重新登入 WordPress 時,就不會出現原有的登入頁面,而是被引導至 WordPress.com 網站,你必須在這裡登入已連結的 WordPress.com 帳號,通過驗證後就可以進入你的控制台囉!

若你在設定途中發現任何問題,導致無法正確登入網站的話,可以把步驟五的程式碼從檔案裡移除,然後將 Jetpack 外掛資料夾整個刪除,就能暫時關閉、停用「單一登入」。

另外,Jetpack 裡也提供了幾個非常實用的模組,建議開啟:

  • Photon 免費 CDN 圖片分流、加速服務,每個 WordPress 用戶都該開啟的外掛
  • Jetpack Monitor 免費 24/7 網站監測服務,WordPress 無法連線自動發送提醒
  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

SpringCloud微服務架構升級總結

一、背景

1.1 應用系統的架構歷史

1.2 什麼是微服務?

起源:微服務的概念源於 2014 年 3 月 Martin Fowler 所寫的一篇文章“Microservices”。文中內容提到:微服務架構是一種架構模式,它提倡將單一應用程序劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值。

通信方式:每個服務運行在其獨立的進程中,服務與服務間採用輕量級的通信機制互相溝通(通常是基於 HTTP 的 RESTful API)。

微服務的常規定義:微服務是一種架構風格,一個大型複雜軟件應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是松耦合的。每個微服務僅關注於完成一件任務。

把原來的一個完整的進程服務,拆分成兩個或兩個以上的進程服務,且互相之間存在調用關係,與原先單一的進程服務相比,就是“微服務”。(微服務是一個比較級的概念,而不是單一的概念)

1.3 微服務架構的優勢

  • 可擴展性:在增加業務功能時,單一應用架構需要在原先架構的代碼基礎上做比較大的調整,而微服務架構只需要增加新的微服務節點,並調整與之有關聯的微服務節點即可。在增加業務響應能力時,單一架構需要進行整體擴容,而微服務架構僅需要擴容響應能力不足的微服務節點。
  • 容錯性:在系統發生故障時,單一應用架構需要進行整個系統的修復,涉及到代碼的變更和應用的啟停,而微服務架構僅僅需要針對有問題的服務進行代碼的變更和服務的啟停。其他服務可通過重試、熔斷等機制實現應用層面的容錯。
  • 技術選型靈活:微服務架構下,每個微服務節點可以根據完成需求功能的不同,自由選擇最適合的技術棧,即使對單一的微服務節點進行重構,成本也非常低。
  • 開發運維效率更高:每個微服務節點都是一個單一進程,都專註於單一功能,並通過定義良好的接口清晰表述服務邊界。由於體積小、複雜度低,每個微服務可由一個小規模團隊或者個人完全掌控,易於保持高可維護性和開發效率。

Spring Cloud作為目前最流行的微服務開發框架,不是採用了Spring Cloud框架就實現了微服務架構,具備了微服務架構的優勢。正確的理解是使用Spring Cloud框架開發微服務架構的系統,使系統具備微服務架構的優勢(Spring Cloud就像工具,還需要“做”的過程)。

1.4 什麼是Spring Boot?什麼是Spring Cloud?

Spring Boot框架是由Pivotal團隊提供的全新框架,其設計目的是用來簡化基於Spring應用的初始搭建以及開發過程。SpringBoot框架使用了特定的方式來進行應用系統的配置,從而使開發人員不再需要耗費大量精力去定義模板化的配置文件。

Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中的配置管理、服務註冊,服務發現、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分佈式會話和集群狀態管理等操作提供了一種簡單的開發方式。

1.5 微服務、Spring Boot、Spring Cloud三者之間的關係

  • 思想:微服務是一種架構的理念,提出了微服務的設計原則,從理論為具體的技術落地提供了指導思想。
  • 腳手架:Spring Boot是一套快速配置腳手架,可以基於Spring Boot快速開發單個微服務。
  • 多個組件的集合:Spring Cloud是一個基於Spring Boot實現的服務治理工具包;Spring Boot專註於快速、方便集成的單個微服務個體;Spring Cloud關注全局的服務治理框架。

二、技術解析

2.1 Everything is jar, Everything is http

Spring Boot通過@SpringBootApplication註解標識為Spring Boot應用程序。所有的應用都通過jar包方式編譯,部署和運行。

@SpringBootApplication 
public class Application {     
    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);     
    public static void main(String[] args) {         
        SpringApplication.run(Application.class, args);         
        LOGGER.info(”啟動成功!");     
    } 
}

 

每個Spring Boot的應用都可以通過內嵌web容器的方式提供http服務,僅僅需要在pom文件中依賴spring-boot-start-web即可,原則上微服務架構希望每個獨立節點都提供http服務。

  <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

 

2.2 Spring boot Task 任務啟動和定時任務

在Spring Boot需要啟動任務時,只要繼承CommandLineRunner接口實現其run方法即可。

@SpringBootApplication 
public class ClientDataListener implements CommandLineRunner
    public void run(String... strings) throws Exception {     
        clientInfoListenerHandler(); 
    }
}

 

在Spring Boot需要執行定時任務時,只需要在定時任務方法上增加@Scheduled(cron = “0 15 0 * * ?”)註解(支持標準cron表達式),並且在服務啟動類上增加@EnableScheduling的註解即可。

@SpringBootApplication
@EnableScheduling
public class Application {     
    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);     
    public static void main(String[] args) {         
        SpringApplication.run(Application.class, args);         
        LOGGER.info(”啟動成功!");     
    } 
}

 

// some class
@Scheduled(cron = "0 15 0 * * ?")
public void someTimeTask() {
    ***
}

 

2.3 Spring boot Actuator 監控

Actuator是spring boot提供的對應用系統自身進行監控的組件,在引入spring-boot-start-web基礎上引入spring-boot-starter-actuator即可。

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

 

2.4 Spring cloud Config 配置中心

在我們實現微服務架構時,每個微服務節點都需要自身的相關配置數據項,當節點眾多,維護就變得非常困難,因此需要建立一个中心配置服務。

Spring Cloud Config分為兩部分。Spring Cloud Config server作為一個服務進程,Spring Cloud Config File為配置文件存放位置。

2.5 Spring cloud Eureka 服務註冊中心

服務註冊的概念早在微服務架構之前就出現了,微服務架構更是把原先的單一應用節點拆分成非常多的微服務節點。互相之間的調用關係會非常複雜,Spring Cloud Eureka作為註冊中心,所有的微服務都可以將自身註冊到Spring Cloud Eureka進行統一的管理和訪問(Eureka和Zookeeper不同,在AOP原則中選擇了OP,更強調服務的有效性)

2.6 Spring cloud Zuul 服務端智能路由

當我們把所有的服務都註冊到Eureka(服務註冊中心)以後,就涉及到如何調用的問題。Spring Cloud Zuul是Spring Cloud提供的服務端代理組件,可以看做是網關,Zuul通過Eureka獲取到可用的服務,通過映射配置,客戶端通過訪問Zuul來訪問實際需要需要訪問的服務。所有的服務通過spring.application.name做標識,

不同IP地址,相同spring.application.name就是一個服務集群。當我們增加一個相同spring.application.name的節點,Zuul通過和Eureka通信獲取新增節點的信息實現智能路由,增加該類型服務的響應能力。

2.7 Spring cloud Ribbon 客戶端智能路由

與Spring Cloud Zuul的服務端代理相對應,Spring Cloud Ribbon提供了客戶端代理。在服務端代理中,客戶端並不需要知道最終是哪個微服務節點為之提供服務,而客戶端代理獲取實質提供服務的節點,並選擇一個進行服務調用。Ribbon和Zuul相似,也是通過和Eureka(服務註冊中心)進行通信來實現客戶端智能路由。

2.8 Spring cloud Sleuth 分佈式追蹤

2.9 Spring cloud Zipkin 調用鏈

2.10 Spring cloud Feign http客戶端

Spring Cloud Feign是一種聲明式、模板化的http客戶端。 使用Spring Cloud Feign請求遠程服務時能夠像調用本地方法一樣,讓開發者感覺不到這是遠程方法(Feign集成了Ribbon做負載均衡)。

把遠程服務和本地服務做映射

@FeignClient(name = "rabbitmq-http", url = "${SKYTRAIN_RABBITMQ_HTTP}") 
public interface TaskService {     
    @RequestMapping(value = "/api/queues", method = RequestMethod.GET)     
    public String query(@RequestHeader("Authorization") String token); 
}

 

以調用本地服務的方式調用遠程服務

@Autowired 
private TaskService taskService; 
private String queryRabbitmqStringInfo() {     
    byte[] credentials = Base64 .encodeBase64((rabbitmqHttpUserName + ":" + rabbitmqHttpPassword).getBytes(StandardCharsets.UTF_8));     
    String token = "Basic " + new String(credentials, StandardCharsets.UTF_8);     
    return taskService.query(token); 
}

 

2.11 Spring cloud Hystrix 斷路器

三、微服務實踐

3.1 我們開發的幾個微服務組件—應用管理中心

應用管理中心可以對每個已經註冊的微服務節點進行停止,編譯,打包,部署,啟動的完整的上線操作。

3.2 我們開發的幾個微服務組件—zookeeper數據查詢中心

zookeeper數據查詢中心根據zookeeper地址,端口,命令獲取zookeeper數據信息。

3.3 我們開發的幾個微服務組件—微服務健康檢測中心

健康檢測中心周期性檢查每個微服務的狀態,當發現有微服務狀態處於DOWN或連接超時時,觸發報警。

3.4 我們開發的幾個微服務組件—定時任務查詢中心

// 在BeanPostProcessor子類中攔截
@Component
public class SkytrainBeanPostProcessor implements BeanPostProcessor, Ordered {
    ***
    /**
     * Bean 實例化之後進行的處理
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        beanPostProcessor.postProcessAfter(bean, beanName);
        return bean;
    }
    ***
}
// 攔截后獲取定時任務註解
***
public Object postProcessAfter(Object bean, String beanName) {
    Class targetClass = AopUtils.getTargetClass(bean);
    Map annotatedMethods = MethodIntrospector.selectMethods(targetClass,
            new MethodIntrospector.MetadataLookup() {
 
                public Set inspect(Method method) {
 
                    Set scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(method,
                            Scheduled.class, Schedules.class);
                    return (!scheduledMethods.isEmpty() ? scheduledMethods : null);
                }
            });
    if (!annotatedMethods.isEmpty()) {
        String className = targetClass.getName();
        for (Map.Entry entry : annotatedMethods.entrySet()) {
            Method method = entry.getKey();
            for (Scheduled scheduled : entry.getValue()) {
                String key = className + ":" + method.getName();
                String value = scheduled.toString();
                taskInfos.put(key, value);
            }
        }
    }
    return null;
}
***
 
// 獲取定時任務后註冊
***
public void taskRegister() {
    String nodeInfo = ipAddress + ":" + serverPort + ":";
    try {
        /**
         * 定時任務
         */
        Map infos = taskInfos;
        for (Entry item : infos.entrySet()) {
            String taskId = nodeInfo + item.getKey();
            String taskParameter = item.getValue();
            JSONObject info = new JSONObject();
            info.put("taskId", taskId);
            info.put("taskParameter", taskParameter);
            info.put("applicationName", applicationName);
            info.put("taskType", "schedule");
            LOGGER.info(info.toString());
            zooKeeperExecutor.createZKNode(SKYTRAIN_TASK_ZKNODE_PREFIX + taskId, info.toString());
        }
    }
    catch (Exception ex) {
        LOGGER.error("", ex);
    }
}
***

 

3.5 微服務的分類

  • 微服務平台組件
  • 公共服務組件
  • 基礎服務組件/業務服務組件

3.6 整體微服務架構圖

作者:梁鑫

來源:宜信技術學院

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

WordPress 桌面版應用程式免費下載!打造閱讀器、離線編輯及管理三合一體驗

前段時間 WordPress 發佈全新管理介面 Calypso,以桌面版應用程式形式提供使用者免費下載,創辦人 Matthew Mullenweg 認為,現今行動裝置非常流行,但一般撰寫或編輯文章仍多半侷限在電腦上進行,因此提供一個最佳化的部落格管理工具就顯得格外重要。這也促使 WordPress 持續獲得更多使用者。

WordPress.com 應用程式一開始只有 Mac 版,現在已延伸至 Windows 及 Linux ,搭配原有 iOS 及 Android 應用程式,幾乎可以說已經完成桌面端及行動裝置佈局。

本文要介紹新推出的 WordPress 應用程式,或者你可以稱它為部落格軟體,這個應用身兼三大功能:閱讀器、離線編輯器及管理工具!以往這三個部分要透過不同服務或軟體來達成,現在,WordPress 原生應用程式就能做到。將資訊來源及內容生產整合在一起,可以說是目前看過最強大的產生力工具。

除此之外,重頭戲仍擺在這次的 Calypso 更新,眾所皆知 WordPress 有非常易用且功能完整的控制台(WP-Admin),但每次要進行操作都必須登入網站,有時候不是那麼方便。WordPress 讓你能直接從桌面端來管理多個網站,全新設計的控制台有非常流暢的操作速度,在管理上更為輕鬆簡單。

不過 WordPress 應用程式最大特色是:可以拿來做為離線編輯器使用!

以往你可能會使用第三方離線編輯器來寫文章,例如:Open Live Writer,因為使用內建文章編輯器並不是那麼方便。在 WordPress 應用程式中,你可以透過全新可視化編輯器來寫文章,內建自動草稿儲存、插入圖片、設定分類與標籤及發佈等功能。

WordPress 應用程式不限於 WordPress.com 使用,如果你是採 WordPress.org 開放原始碼程式自行架站,安裝 Jetpack 一樣能夠支援。這是一款由 Automattic(WordPress 母公司)開發的外掛程式,包含幾項我曾介紹過的功能:

  • Photon 免費 CDN 圖片分流加速服務
  • Jetpack Monitor 免費 24/7 網站監測服務,網站無法連線自動提醒
  • 啟用 Jetpack「單一登入」機制教學,讓你的 WordPress 網站更安全

當然,如果你是使用 WordPress.com 免費部落格服務,只要下載應用程式,登入你的帳號密碼,即可讓軟體與你的部落格連線。

軟體資訊

軟體名稱:WordPress.com 桌面應用程式
軟體語系:多國語言
作業系統:Windows、Mac、Linux
官方網站:https://desktop.wordpress.com/
下載鏈結:官方網站免費下載

使用教學

STEP 1

開啟 WordPress.com 應用程式後,輸入你的使用者名稱、密碼來登入,這裡要輸入的不是你網站的登入帳號密碼,而是網站所連結的 WordPress.com 帳號資訊。

若你是使用 WordPress 自行架站,點選下方「Add self-hosted site」取得更多資訊。

STEP 2

WordPress.com 應用程式的預設畫面為「讀取器」,也就是前面提到的閱讀器。在這裡可以將你喜歡的網站內容加入「關注」,WordPress 會推薦你可能有興趣的相關網站內容。你還可以新增清單、加上標籤來分類不同的網站主題。

在閱讀器裡,你可以新增任何有 RSS Feed 功能的網站,不限於 WordPress 類型。

STEP 3

WordPress.com 應用程式的另一個特色是可以隨時收到通知。它就像一般軟體,當有人關注你,在你的網站按讚或留言,它會立即跳出提示讓你知道。

STEP 4

這個應用程式的亮點應該是管理功能,或許你之前在網頁端試用過,軟體把操作介面帶到桌面端,讓你不用從瀏覽器就能進行網站管理,包括新增文章頁面,或是更新升級佈景主題及外掛等等(必須從 Jetpack 開啟「Manage」模組才能用)。

不過我最喜歡的是 WordPress.com 的統計功能(Stats),它會清楚記錄下每天的網站流量變化,包括最熱門的文章頁面、來源網址、國家等資訊,相較於 Google 分析來說,內建的統計資料更為清楚易懂。

STEP 5

前面介紹有提到:WordPress 桌面版應用程式本身就是一個離線編輯器!現在,你可以直接在桌面端透過官方軟體來撰寫文章。

應用程式的編輯器功能非常好用,不但速度快、設計簡單大方,也和 WordPress 有更緊密的結合,因為它已經加入了網站相關設定,例如分類與標籤、特色圖片、分享等功能。

下圖是我使用 WordPress.com App for Windows 桌面版來寫文章的畫面擷圖,可以看到相較於原先網頁編輯器來說,桌面版設計更為乾淨明亮,讓你在寫文章時有更好的寫作體驗(如果常常苦思得不到靈感,就會知道這有多麼重要…)。

這個編輯器的另一特色是:無須連上網路,具備自動儲存草稿功能。若你正在尋找一款免費、好用的部落格寫作工具,WordPress.com App 會是非常棒的選擇!

WordPress 本身只是一個開放原始碼的 PHP 程式,用於架設網站部落格,但憑藉外掛功能,讓它延伸擴展更多更不一樣的變化!Matthew Mullenweg 始終相信開放相較於封閉有更多的好處,WordPress 彈性自由更可以適應不斷變化的網路環境。

這款 WordPress.com 桌面版應用程式耗時二十個月,由來自世界各地的開發者貢獻而生,相信它能跟上接下來的發展趨勢,讓我們有更為便利的數位寫作工具!

值得一試的三個理由:

  1. 開放原始碼,提供 Windows、Mac、Linux 三大平台免費下載
  2. 更好用的寫作工具,將重心聚焦於內容
  3. 速度快、操作簡單,使用現今最流行開發項目
  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

Hostinger 頂級免費虛擬主機推薦,練習架站最佳 PHP、MySQL 平台

雖然免費資源網路社群有免費網站空間分類,但讀者會發現,我已經很久沒有介紹免費虛擬主機服務,原因很簡單,因為太多免空到後來都變得極為不穩定,甚至無預警關閉服務,對於架站者來說,辛苦經營網站被停用,不僅損失寶貴內容,更是對於免費服務劃上一個大大的問號。因此我會建議真正想架站的朋友花點錢去租用虛擬主機,尤其現在價格相較於幾年前來說已經非常實惠,搭配申請網域名稱可能每個月只要幾百元左右就能輕鬆架站。

不過還是很多人跑來問我:有沒有推薦的免費虛擬主機呢?如果你純粹想練習架站,又不想要花錢(或者想先試試看 WordPress 或其他架站程式是不是合乎你的需求),本文要來介紹一個老牌頂級免費虛擬主機服務。

Hostinger 是一個在全球超過 35 個國家提供免費虛擬主機的公司,旗下還有幾個可能你曾經見過的經銷主機(Reseller Hosting,例如 YouHosting)、帳務管理、VPS 和網站建置服務。Hostinger 提供免費內建 PHP、MySQL 架站空間,預設 2000 MB(2 GB)空間、每月 100 GB 流量限制,最棒的是具備中文介面,而且沒有任何廣告!

或許你曾經聽過或使用過 cPanel 主機,Hostinger 就是一個客製化 cPanel 控制台,可以在平台上使用各項功能。本身也提供付費升級,只要支付費用就能獲得無限制空間。之所以會想介紹 Hostinger ,除了有很簡單易懂中文控制台,內建一鍵快速安裝各種程式功能,讓你在架站時更快、更順暢,也能將資料庫匯出,將網站搬移到其他空間。

不過還是要再次提醒:Hostinger 並非長久之計!如果你想要認真經營網站、部落格,或是想透過架站來協助你達成某些目的,那麼最終仍要走上付費服務一途,不過相較於其他免費空間來說,Hostinger 無論在速度或穩定性都值得一用。本文會介紹如何申請 Hostinger 以及透過它來架設一個中文 WordPress 網站。

網站名稱:Hostinger
網站鏈結:http://www.hostinger.com.hk/

使用教學

第一步,申請 Hostinger 免費版帳號

開啟 Hostinger 中文版網站後,會有簡體中文版介面,雖然 Hostinger 在全世界很多國家都有提供在地化語言網站,但其實功能操作上並沒有太大不同。點選首頁的「現在訂購」就能開始申請帳號。

申請時直接以 Google 帳號登入,或者輸入姓名、Email 及密碼來註冊帳號。

註冊後必須先到信箱收取 Email,點選信中的確認鏈結才能啟用帳號,跟一般我們熟悉的網路服務相同。啟用帳號後點選藍色「主機」下方的「新主機」來開啟第一個空間。

第二步,開啟第一個 PHP、MySQL 網站空間

申請帳號後 Hostinger 不會自動幫你建立主機帳號,因此要點選「新主機帳號」按鈕來開啟新帳號,在這裡可以點選右上角來切換語言,Hostinger 提供繁體中文,不過預設情況下是使用簡體中文。

Hostinger 提供免費版、高級版和商業版三種套餐組合,在這裡選擇「免費版」繼續。如果你需要更多的空間或流量限制、SSH 或選擇更穩定的伺服器節點,可以付費升級。

接著設定一個要使用的免費二級網域名稱,Hostinger 提供一些簡短後綴,或者你也可以切換回一級域名來綁定自己申請的網址,之後再把 DNS 對應到 Hostinger 就能使用。

免費方案只能選擇位於英國的伺服器區域,速度上可能相較於美國來說會慢一些,不過整體來說還算穩定,付費的話可選擇包括美國、新加坡、巴西及俄羅斯在內等其他區域。最後設定好密碼就能建立免費空間。

在確定送出申請表單前,Hostinger 會要求使用者輸入你申請帳號的用途,可以寫一些你要架設網站目的、類型或相關原因。因為 Hostinger 每天收到超過兩萬封免費空間申請,為了過濾嚴重的濫用情形會多一道審核程序。

我在申請後 Hostinger 空間就立即開通,狀態顯示為「已激活」就表示可以使用啦!

第三步,使用 Hostinger 架設 WordPress 網站教學

點選你的空間會開啟更多功能,包括「管理」、「自助建站」、「一鍵安裝助手」以及比較少人用到的「E-mail」,點選「管理」就能開啟 cPanel 控制台,不過在這裡我要先示範如何快速安裝一個 WordPress 網站,我們點選「一鍵安裝助手」來開啟快速架站功能。

如果有用過 cPanel 的話,應該知道它有提供快速架站工具,內建許多常見與不常見的開放原始碼專案程式,能讓我們快速建置出 CMS、部落格、討論區或其他服務,從中找出我們要使用的 WordPress,點選來進行安裝。

設定一下安裝路徑、語言(可以選擇臺灣,有正體中文)、管理員帳號密碼、E-mail,網站標題跟標語之後可以隨時再做修改調整,最後點選「安裝」就能自動架站。

不得不說 Hostinger 或類 cPanel 網站空間的自動化架站程式非常好用,只要幾秒鐘時間就能把 WordPress 網站架設完成!在網址後面加上 /wp-admin/ 可以開啟控制台,不過你會先遇到登入畫面,輸入剛才安裝時設定的管理員帳號密碼。

從 WordPress 後台就能對網站進行完整操控,包括更換佈景主題、安裝外掛功能、加入新帳號,以及新增文章、頁面、媒體等等,Hostinger 快速架站功能會在安裝後內建一些外掛程式,不需要的話可以把它停用移除(沒想到還內建兩階段功能的 Clef ,我曾經有寫過專文來介紹這個外掛)。

現在,你就簡單架設好一個 WordPress 網站了!

延伸閱讀:

  • WordPress 桌面版應用程式免費下載!打造閱讀器、離線編輯及管理三合一體驗
  • 殺手級 WordPress 體檢項目:101 個建立新網站的超簡易捷徑!
  • 安裝 WordPress 後你應該做的 25 件事
  • 11 個強化 WordPress 網站安全的 .Htaccess 設定技巧

後記

前面有提到,Hostinger 本身已有一個客制化的 cPanel 控制台,因此使用者可以很方便快速地從控制台進行虛擬主機相關操作,不僅限於架設 WordPress,若是其他的開放原始碼程式或單純的 HTML 網站都能勝任。

如果你不常接觸這類的架站平台,cPanel 是個很容易上手的選擇,之後若要租用其他付費主機,也可以尋找使用 cPanel 控制台的服務。

另外,Hostinger 已經支援最新的 PHP 7.0,我建議可以從控制台的「高級 -> PHP 版本切換」來進行設定,將它選擇到 PHP 7 以獲得更好的速度及效能。

最後,如果你想使用 Hostinger 架站,請務必要備份好自己的檔案,因為免費空間並不會保障你的使用權益,且可能因為不夠穩定或任何因素而發生問題,若有備份的話,就能隨時搬遷到其他虛擬主機上。此外,我也建議無論如何都要註冊一個網域名稱,未來當你搬移空間時就不用重新開始啦!

  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

TDD(測試驅動開發)死了嗎?

01、前言

很早之前,曾在網絡上見到過 TDD 這 3 個大寫的英文字母,它是 Test Driven Development 這三個單詞的縮寫,也就是“測試驅動開發”的意思——聽起來很不錯的一種理念。

其理念主要是確保兩件事:

  • 確保所有的需求都能被照顧到。
  • 在代碼不斷增加和重構的過程中,可以檢查所有的功能是否正確。

但後來很長一段時間里,都沒再聽過 TDD 的消息。有人說,TDD 已經死了,給出的意見如下:

1)通常來說,開發人員不應該在沒有失敗的測試用例下編寫代碼——這似乎是合理的,但是它可能導致過度測試。例如,為了保證一行生產代碼的正確性,你不由得寫了 4 行測試代碼,這意味着一旦這一行生產代碼需要修改,你也得修改那 4 行測試代碼。

2)為了遵循 TDD 而寫的代碼,容易進入一個誤區:代碼是為了滿足測試用的,而忽略了實際需求。

02、TDD 到底是什麼?

不管 TDD 到底死了沒有,先讓我們來回顧一下 TDD 到底是什麼。

TDD 的基本思想就是在開發功能代碼之前,先編寫測試代碼。也就是說在明確要開發某個功能后,首先思考如何對這個功能進行測試,並完成測試代碼的編寫,然後編寫相關的代碼滿足這些測試用例。然後循環進行添加其他功能,直到完成全部功能的開發。

TDD 的基本過程可以拆解為以下 6 個步驟:

1) 分析需求,把需求拆分為具體的任務。

2) 從任務列表中取出一個任務,並對其編寫測試用例。

3) 由於沒有實際的功能代碼,測試代碼不大可能會通過(紅)。

4) 編寫對應的功能代碼,儘快讓測試代碼通過(綠)。

5) 對代碼進行重構,並保證測試通過(重構)。

6) 重複以上步驟。

可以用下圖來表示上述過程。

03、TDD 的實踐過程

通常情況下,我們都習慣在需求分析完成之後,儘快地投入功能代碼的編寫工作中,之後再去調用和測試。

而 TDD 則不同,它假設我們已經有了一個“測試用戶”了,它是功能代碼的第一個使用者,儘管功能代碼還不太完善。

當我們站在“測試用戶”的角度去寫測試代碼的時候,我們要考慮的是,這個“測試用戶”該如何使用功能代碼呢?是通過一個類直接調用方法呢(靜態方法),還是構建類的實例去調用方法呢(實例方法)?這個方法如何傳參呢?方法如何命名呢?方法有返回值嗎?

有了測試代碼后,我們開始編寫功能代碼,並且要以最快地速度讓測試由“紅”變為“綠”,可能此時的功能代碼很不優雅,不過沒關係。

當測試通過以後,我們就可以放心大膽的對功能代碼進行“重構”了——優化原來比較醜陋、臃腫、性能偏差的代碼。

接下來,假設我們接到了一個開發需求:

汪汪隊要到小鎮冒險島進行表演,門票為 99 元,冒險島上唯一的一個程序員王二需要開發一款可以計算門票收入的小程序。

按照 TDD 的流程,王二需要先使用 Junit 編寫一個簡單的測試用例,測試預期是:銷售一張門票的收入是 99 元。

public class TicketTest {

    private Ticket ticket;

    @Before
    public void setUp() throws Exception {
        ticket = new Ticket();
    }

    @Test
    public void test() {
        BigDecimal total = new BigDecimal("99");

        assertEquals(total, ticket.sale(1));
    }

}

為了便於編譯能夠順利通過,王二需要一個簡單的 Ticket 類:

public class Ticket {

    public BigDecimal sale(int count) {
        return BigDecimal.ZERO;
    }

}

測試用例運行結果如下圖所示,紅色表示測試沒有通過:預期結果是 99,實際結果是 0。

那接下來,王二需要快速讓測試通過,Ticket.sale() 方法修改后的結果如下:

public class Ticket {

    public BigDecimal sale(int count) {
        if (count == 1) {
            return new BigDecimal("99");
        }
        return BigDecimal.ZERO;
    }

}

再運行一下測試用例,結果如下圖所示,綠色表示測試通過了:預期結果是 99,實際結果是 99。

綠了,綠了,測試通過了,到了該重構功能代碼的時候了。99 元是個魔法数字,至少應該聲明成常量,對吧?

public class Ticket {
    private final static int PRICE = 99;

    public BigDecimal sale(int count) {
        if (count == 1) {
            return new BigDecimal(PRICE);
        }
        return BigDecimal.ZERO;
    }

}

重構完后再運行一下測試用例,確保測試通過的情況下,再增加幾個測試用例,比如說門票銷量為負數、零甚至一千的情況。

public class TicketTest {

    private Ticket ticket;

    @Before
    public void setUp() throws Exception {
        ticket = new Ticket();
    }

    @Test
    public void testOne() {
        BigDecimal total = new BigDecimal("99");

        assertEquals(total, ticket.sale(1));
    }

    @Test(expected=IllegalArgumentException.class)
    public void testNegative() {
        ticket.sale(-1);
    }

    @Test
    public void testZero() {
        assertEquals(BigDecimal.ZERO, ticket.sale(0));
    }

    @Test
    public void test1000() {
        assertEquals(new BigDecimal(99000), ticket.sale(1000));
    }

}

銷量為負數的時候,王二希望功能代碼能夠拋出異常;銷量為零的時候,功能代碼的計算結果應該為零;銷量為一千的時候,計算結果應該為 99000。

重新運行一下測試用例,結果如下圖所示:

有兩個測試用例沒有通過,那麼王二需要繼續修改功能代碼,調整如下:

public class Ticket {
    private final static int PRICE = 99;

    public BigDecimal sale(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("銷量不能為負數");
        }

        if (count == 0) {
            return BigDecimal.ZERO;
        }

        if (count == 1) {
            return new BigDecimal(PRICE);
        }

        return new BigDecimal(PRICE * count);
    }

}

再運行一下測試用例,發現都通過了。又到了重構的時候了,銷量為零、或者大於等於一的時候,代碼可以合併,於是重構結果如下:

public class Ticket {
    private final static int PRICE = 99;

    public BigDecimal sale(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("銷量不能為負數");
        }

        return new BigDecimal(PRICE * count);
    }

}

重構結束后,再運行測試用例,確保重構后的代碼依然可用。

04、最後

從上面的實踐過程可以得出如下結論:

TDD 想要做的就是讓我們對自己的代碼充滿信心,因為我們可以通過測試代碼來判斷這段代碼是否正確無誤。

也就是說,TDD 流程比較關鍵的一環在於如何寫出有效的測試代碼,這裡有 4 個原則可以參考:

1)測試過程應該盡量模擬正常使用的過程。

2)應該盡量做到分支覆蓋。

3)測試數據應該盡量包括真實數據,以及邊界數據。

4)測試語句和測試數據應該盡量簡單,容易理解。

注意,這 4 個原則不僅適用於 TDD,同樣適用於任何流程下的單元測試。

最後,我想說的是,不管 TDD 有沒有死,TDD 都不是銀彈,不可能適合所有的場景,但這不應該成為我們拒絕它的理由。

 

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

100HUB 免費台灣虛擬主機,採Plesk控制台

有不少朋友問我,這幾年好像很少介紹免費虛擬主機?原因很簡單,因為不容易找到我認為足夠穩定、可靠的選項,尤其虛擬主機維持長時間營運實屬不易,通常要有其他營利項目才足以打平開支,對於沒有先經過一段時間「洗禮」的服務我不輕易推薦給讀者。當然要架站的話我認為還是去付費租用虛擬主機會比較可靠一些,例如我在 WordPress 教學文件就曾經推薦過五個虛擬主機服務,價格都不貴,而且有不滿意全額退款保證。

本文要介紹的免費虛擬主機服務 100HUB 並不是新服務,除了提供免費但有廣告的虛擬主機外,也有不同客戶族群適用的主機方案,包括 VPS、網域名稱及 SSL 憑證等項目。如果你不想那麼快付費,想先試試看使用 WordPress 架站是否合乎你的需求,那麼免費的廣告型虛擬主機或許是可考慮的選擇。

100HUB「威利 100 專業主機」是我在 CloudFlare 合作夥伴找到的少數台灣主機商,因為有合作關係,支援 Railgun 功能,100hub.com 客戶搭配 CloudFlare 時將可以獲得更快的連線速度!可惜的是免費虛擬主機不支援 Railgun,但因為主機位於日本,從台灣或亞洲任何國家連線速度都是相當順暢的。

100HUB 免費虛擬主機分成兩種,一種是免費試用 14 天,另一種是廣告型免費主機,但能永久使用,而現今大部分虛擬主機服務都已有不滿意全額退款保證,有時間限制的試用方案倒不那麼吸引人,我會建議使用廣告型空間(沒有時間限制),如果你只是想要練習架站或個人部落格,這個方案規格已相當充裕。

廣告型免費主機提供 300 MB 空間,每月有 6 GB 流量限制,主機位於日本 GMO 東京機房,從台灣連線速度很不錯,對於小型個人網站或部落格來說已經非常充裕。不過必須要提醒的是 100HUB 採用 Plesk 控制台,而不是大部分使用者熟悉的 cPanel,一樣也有提供中文介面,若不是非 cPanel 不用的話倒是沒什麼影響。

接下來我簡單介紹 100HUB 免費日本虛擬主機的註冊申請方式,以及如何在 Plesk 快速架設一個自己的 WordPress 網站。

網站名稱:100HUB 威利100專業主機
網站鏈結:https://100hub.com/

使用教學

申請 100HUB 免費日本虛擬主機教學

STEP 1

開啟 100HUB.com 網站後,從首頁的規格方案中點選「免費」下方「立即申請」,接著會看到三種免費產品,其中有兩種是免費試用 14 天,最後一種為「廣告型免費主機」,我們點選廣告型免費主機最下方的「馬上申請」鏈結。

由於註冊新的網域名稱或移轉(Transfer)都必須付費,因此我們選擇使用 100HUB 提供的免費域名,網址結尾為 .100hub.net,設定一個你要使用的名稱。

STEP 2

如果你選擇的名稱還沒有被佔用,就會跳出支付結帳畫面,價格確認為 0 元,沒問題的話點選右側「結帳」綠色按鈕來跳到下一個畫面。

STEP 3

接著要填寫你的個人資料和帳單資訊,100hub.com 規定使用者必須填寫正確且可供驗證的資料,這部分記得花點時間填寫,如果亂填或資料有誤可能無法通過審核。

STEP 4

註冊後,你的 100HUB 免費帳戶狀態會顯示為「確認中」,大約要等待數小時,站方審核後才會開通、啟用帳號。

使用虛擬主機快速架設 WordPress

STEP 1

當 100hub.com 審核完你的免費虛擬主機申請,就會以 Email 通知,從主機商的控制台可以取得包括使用者名稱、主機名稱、IP 位址和進入 PLESK 後台的登入鏈結。

STEP 2

下圖就是 HUB100 免費虛擬主機使用的 PLESK 控制台介面,怎麼看起來好像跟印象中差了很多?無論如何,控制台就是一個網站最核心的部分,從這裡可以進行主機設定、應用程式安裝、網域名稱管理、Email、資料庫、統計等功能,因此要妥善保存你的帳號密碼。

點選 PLESK 控制台左側選單的「應用程式」,找到「WordPress」後按下「安裝」,當然你也可以選擇要安裝的 WordPress 版本(建議還是以安裝最新版為主)。

STEP 3

選好後就會以自動化工具來安裝、設定 WordPress,其實 WordPress 本身安裝介面設計已經非常簡單,甚至可以在五分鐘以內架設好一個網站,不過如果使用自動化安裝程式的話幾乎不用做任何設定,可以算是最快的安裝法。

安裝後,PLRSK 會顯示你的網址、安裝位置、帳號密碼,建議把「自動更新」功能開啟以增加安全性,未來當有任何新的版本釋出,WordPress 就會自動更新檔案,以保持你的網站在最新、最安全狀態。

STEP 4

進入你的 WordPress 網站後,點選側邊欄右下角的「登入」,以 PLESK 提供的帳號密碼即可登入控制台。或者你可以先試著體驗一下 100HUB 免費虛擬主機的速度,我在台灣連線速度是還蠻快的,換頁也不會有感覺卡卡的問題。

因為 100HUB 免費虛擬主機是會顯示廣告的,因此左下角會有一個 LOGO 圖案,但廣告只是一個鏈結,不會侵入你的內容部分,倒也還可以接受。

如果你覺得自動化安裝工具設定的帳號密碼很難記憶,記得在登入後從「帳號」功能來新增新的管理員帳戶,這麼做除了可增加安全性外,亦能將最初建立的帳號移除,同時熟悉一下 WordPress 帳戶權限設定。

開始享受你的網站吧!

當然,免費虛擬主機不是只能安裝 WordPress,你也可以安裝其他開放原始碼程式,或者拿來單純做為 HTML 網頁託管使用,並沒有侷限於單一功能,不過還是要提醒,如果有任何重要內容,不建議直接放到免費主機上,因為無法保證網站能夠持續運作,若要使用免費主機,也記得要時時備份網站資料,以免發生任何狀況而讓資料遺失無法救回喔!

  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

Cloudflare 免費 WordPress 外掛教學,一鍵為網站快速套用最佳化設定


(Photo credit: TechCrunch via Visualhunt / CC BY)

最近 CloudFlare 在台灣網路圈吵蠻兇的,起因是 CloudFlare 八月在自家網站公布服務在全世界各地頻寬支出成本(參考資料:Bandwidth Costs Around the World),其中點名的六家超高成本 ISP 業者在亞洲就有台灣中華電信 HiNet 及韓國電信,相較於歐洲或北美支出的頻寬成本來說多出 15 倍!CloudFlare 為了提出抗議,更大動作將連線到使用 CloudFlare 服務網站的中華電信使用者導向頻寬成本較低的美國西岸節點。

其實連到美西頻寬夠大,速度倒也不是非常糟,畢竟很多網站都選擇放在開銷較低的國外機房,那麼這段距離對於台灣使用者開啟網站的速度並沒有太大影響。但恰巧中華電信近期發生海底電纜異常,尖峰時段連線壅塞造成很多網站無法打開,才會有好像取消台灣節點造成網站變慢的問題。

撇開這些狀況不說,我還是推薦架站時搭配 CloudFlare 提供的免費 CDN 來加速網站連線速度,同時遏止任何可能的攻擊或安全問題,類似服務還有 Incapsula,但沒有它來得這麼全面(目前 CF 節點數也是同類服務之冠)。

關於 CloudFlare 使用教學我在「CloudFlare 架站者必備免費 CDN、DNS 託管服務設定教學,網站載入加速、節省流量防止惡意攻擊」一文有完整說明,若你是使用 WordPress 架站,我建議你務必安裝全新 CloudFlare 外掛,它為 WP 使用者提供更多功能。

早先 WordPress 的 CloudFlare 外掛只有解析 IP 功能,讓無法在控制台迴響顯示使用者真實 IP 位址的問題得以解決;近期 CloudFlare 外掛更新,將設定選項帶進 WordPress 控制台,往後將可以在控制台進行一些基本的設定或操作,也能查看分析報表。

網站名稱:CloudFlare for WordPress
網站鏈結:https://tw.wordpress.org/plugins/cloudflare/

使用教學

STEP 1

登入 WordPress 控制台後,點選左側選單的「外掛 -> 安裝外掛」,右上角填入 CloudFlare 會跳出相關結果,第一個就是來自 CloudFlare 官方的外掛功能,點選「立即安裝」即可將它下載安裝到網站。

在外掛列表中將 CloudFlare 啟用,設定裡就會多一個 CF 設定頁面。

STEP 2

不過要在控制台使用 CloudFlare 功能,必須要連結到你 CF 帳戶,驗證方法是 Email 加上你的 API 密鑰,這組密鑰在哪呢?只要開啟 CloudFlare 控制台並點選右上角的 My Settings 就能找到(網頁下方的 Global API Key,點選 View API Key 就會顯示)。

這組密鑰非常重要,等同於你的密碼,切勿將它告訴其他人。

回到 WordPress 的 CloudFlare 設定頁面,輸入你的 CloudFlare 帳號(Email)及 API Key 就能成功串連,基本上登入畫面只需要設定一次,之後就不會再次出現。

STEP 3

接著會看到 CloudFlare 在全新 3.0 版加入的所有功能,介面也變得跟以前不同。

如果你剛開始接觸 CF,沒有太多時間來詳細研究各項設定,推薦你直接使用第一項設定的「Apply Default Settings」一鍵套用最適合網站效能的建議設定值,這也是此次更新後我認為最喜愛的功能。

STEP 4

CloudFlare 在新的 WordPress 外掛程式上已經加入清理快取(Purge Cache)和自動化完整快取管理(Automatic Full Cache Management)功能,若開啟後當你更新網站選項時就會自動清理 CloudFlare 的快取內容。不過預設情況下其實不太需要打開,因為網站頁面並不會被 CloudFlare 快取,只有圖片等靜態元件才會。

STEP 5

另外,設定頁右上角的「Enable “Im Under Attack” Mode」是一項很特殊的功能,如果你認為你的網站正遭遇攻擊,或者有人想嘗試登入網站(例如使用暴力破解),點選後就能使網站獲得更高安全性的保護措施。

正常情況下並不建議開啟這項功能,因為很可能會使一般訪客在瀏覽時發生問題。

STEP 6

其他設定選項在「More Settings」可以找到,完整設定項目建議回到 CloudFlare 調整修改,外掛裡沒有涵蓋所有選項。但還是要補充一下,從 Analytics 裡可以看到 CF 端的分析圖表了!這也是此次更新中非常令人振奮的全新功能。

  • 按一下以分享至 Facebook(在新視窗中開啟)
  • 分享到 Twitter(在新視窗中開啟)
  • 分享到 LinkedIn(在新視窗中開啟)
  • 分享到 Pinterest(在新視窗中開啟)
  • 分享到 Pocket(在新視窗中開啟)

相關文章

本站聲明:網站內容來源免費資源網路社群https://free.com.tw,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!

【算法隨記三】小半徑中值模糊的急速實現(16MB圖7.5ms實現) + Photoshop中蒙塵和划痕算法解讀。,任意半徑中值濾波(擴展至百分比濾波器)O(1)時間複雜度算法的原理、實現及效果,任意半徑中值濾波(擴展至百分比濾波器)O(1)時間複雜度算法的原理、實現及效果

  在本人的博客里,分享了有關中值模糊的O(1)算法,詳見:任意半徑中值濾波(擴展至百分比濾波器)O(1)時間複雜度算法的原理、實現及效果 ,這裏的算法的執行時間和參數是無關的。整體來說,雖然速度也很快,但是在某些特殊情況下我們還是需要更快的速度。特別是對於小半徑的中值,我們有理由去對其進一步的優化的。本文我們進一步探討這個問題。

  一、3*3中值模糊

  首先我們來看看半徑為1的中值,此時涉及到的領域為3*3,共9個像素,那麼最傳統的實現方式就是對9個像素直接進行排序,這裏我們直接使用系統的排序函數qsort,一種簡單的代碼如下所示:

int __cdecl ComparisonFunction(const void *X, const void *Y)        // 一定要用__cdecl這個標識符
{ unsigned char Dx = *(unsigned char *)X; unsigned char Dy = *(unsigned char *)Y; if (Dx < Dy) return -1; else if (Dx > Dy) return +1; else
        return 0; } void MedianBlur3X3_Ori(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride) { int Channel = Stride / Width; if (Channel == 1) { unsigned char Array[9]; for (int Y = 1; Y < Height - 1; Y++) { unsigned char *LineP0 = Src + (Y - 1) * Stride + 1; unsigned char *LineP1 = LineP0 + Stride; unsigned char *LineP2 = LineP1 + Stride; unsigned char *LinePD = Dest + Y * Stride + 1; for (int X = 1; X < Width - 1; X++) { Array[0] = LineP0[X - 1];        Array[1] = LineP0[X];    Array[2] = LineP0[X + 1]; Array[3] = LineP1[X - 1];        Array[4] = LineP1[X];    Array[5] = LineP2[X + 1]; Array[6] = LineP2[X - 1];        Array[7] = LineP2[X];    Array[8] = LineP2[X + 1]; qsort(Array, 9, sizeof(unsigned char), &ComparisonFunction); LinePD[X] = Array[4]; } } } else { unsigned char ArrayB[9], ArrayG[9], ArrayR[9]; for (int Y = 1; Y < Height - 1; Y++) { unsigned char *LineP0 = Src + (Y - 1) * Stride + 3; unsigned char *LineP1 = LineP0 + Stride; unsigned char *LineP2 = LineP1 + Stride; unsigned char *LinePD = Dest + Y * Stride + 3; for (int X = 1; X < Width - 1; X++) { ArrayB[0] = LineP0[-3];       ArrayG[0] = LineP0[-2];       ArrayR[0] = LineP0[-1]; ArrayB[1] = LineP0[0];        ArrayG[1] = LineP0[1];        ArrayR[1] = LineP0[2]; ArrayB[2] = LineP0[3];        ArrayG[2] = LineP0[4];        ArrayR[2] = LineP0[5]; ArrayB[3] = LineP1[-3];       ArrayG[3] = LineP1[-2];       ArrayR[3] = LineP1[-1]; ArrayB[4] = LineP1[0];        ArrayG[4] = LineP1[1];        ArrayR[4] = LineP1[2]; ArrayB[5] = LineP1[3];        ArrayG[5] = LineP1[4];        ArrayR[5] = LineP1[5]; ArrayB[6] = LineP2[-3];       ArrayG[6] = LineP2[-2];       ArrayR[6] = LineP2[-1]; ArrayB[7] = LineP2[0];        ArrayG[7] = LineP2[1];        ArrayR[7] = LineP2[2]; ArrayB[8] = LineP2[3];        ArrayG[8] = LineP2[4];        ArrayR[8] = LineP2[5]; qsort(ArrayB, 9, sizeof(unsigned char), &ComparisonFunction); qsort(ArrayG, 9, sizeof(unsigned char), &ComparisonFunction); qsort(ArrayR, 9, sizeof(unsigned char), &ComparisonFunction); LinePD[0] = ArrayB[4]; LinePD[1] = ArrayG[4]; LinePD[2] = ArrayR[4]; LineP0 += 3; LineP1 += 3; LineP2 += 3; LinePD += 3; } } } }

  代碼很簡潔和清晰,我們沒有處理邊緣的那一圈像素,這無關精要,我們編譯后測試,結果如下所示:

  1920*1080大小的24位圖像,平均用時1280ms,灰度圖像平均用時460ms,這相當的慢,無法接受。

  下面我們稍微對其進行下提速。

  對於9個數據的排序,我們可以對其進行特殊的處理,因為數據的個數是確定的,按照理論分析,沒有必要進行大規模的比較,實際只需要進行19次比較就可以了。修改后算法如下所示:

inline void Swap(int &X, int &Y) { X ^= Y; Y ^= X; X ^= Y; } void MedianBlur3X3_Faster(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride) { int Channel = Stride / Width; if (Channel == 1) { for (int Y = 1; Y < Height - 1; Y++) { unsigned char *LineP0 = Src + (Y - 1) * Stride + 1; unsigned char *LineP1 = LineP0 + Stride; unsigned char *LineP2 = LineP1 + Stride; unsigned char *LinePD = Dest + Y * Stride + 1; for (int X = 1; X < Width - 1; X++) { int Gray0, Gray1, Gray2, Gray3, Gray4, Gray5, Gray6, Gray7, Gray8; Gray0 = LineP0[X - 1];        Gray1 = LineP0[X];    Gray2 = LineP0[X + 1]; Gray3 = LineP1[X - 1];        Gray4 = LineP1[X];    Gray5 = LineP2[X + 1]; Gray6 = LineP2[X - 1];        Gray7 = LineP2[X];    Gray8 = LineP2[X + 1]; if (Gray1 > Gray2) Swap(Gray1, Gray2); if (Gray4 > Gray5) Swap(Gray4, Gray5); if (Gray7 > Gray8) Swap(Gray7, Gray8); if (Gray0 > Gray1) Swap(Gray0, Gray1); if (Gray3 > Gray4) Swap(Gray3, Gray4); if (Gray6 > Gray7) Swap(Gray6, Gray7); if (Gray1 > Gray2) Swap(Gray1, Gray2); if (Gray4 > Gray5) Swap(Gray4, Gray5); if (Gray7 > Gray8) Swap(Gray7, Gray8); if (Gray0 > Gray3) Swap(Gray0, Gray3); if (Gray5 > Gray8) Swap(Gray5, Gray8); if (Gray4 > Gray7) Swap(Gray4, Gray7); if (Gray3 > Gray6) Swap(Gray3, Gray6); if (Gray1 > Gray4) Swap(Gray1, Gray4); if (Gray2 > Gray5) Swap(Gray2, Gray5); if (Gray4 > Gray7) Swap(Gray4, Gray7); if (Gray4 > Gray2) Swap(Gray4, Gray2); if (Gray6 > Gray4) Swap(Gray6, Gray4); if (Gray4 > Gray2) Swap(Gray4, Gray2); LinePD[X] = Gray4; } } } else { for (int Y = 1; Y < Height - 1; Y++) { unsigned char *LineP0 = Src + (Y - 1) * Stride + 3; unsigned char *LineP1 = LineP0 + Stride; unsigned char *LineP2 = LineP1 + Stride; unsigned char *LinePD = Dest + Y * Stride + 3; for (int X = 1; X < Width - 1; X++) { int Blue0, Blue1, Blue2, Blue3, Blue4, Blue5, Blue6, Blue7, Blue8; int Green0, Green1, Green2, Green3, Green4, Green5, Green6, Green7, Green8; int Red0, Red1, Red2, Red3, Red4, Red5, Red6, Red7, Red8; Blue0 = LineP0[-3];        Green0 = LineP0[-2];    Red0 = LineP0[-1]; Blue1 = LineP0[0];        Green1 = LineP0[1];        Red1 = LineP0[2]; Blue2 = LineP0[3];        Green2 = LineP0[4];        Red2 = LineP0[5]; Blue3 = LineP1[-3];        Green3 = LineP1[-2];    Red3 = LineP1[-1]; Blue4 = LineP1[0];        Green4 = LineP1[1];        Red4 = LineP1[2]; Blue5 = LineP1[3];        Green5 = LineP1[4];        Red5 = LineP1[5]; Blue6 = LineP2[-3];        Green6 = LineP2[-2];    Red6 = LineP2[-1]; Blue7 = LineP2[0];        Green7 = LineP2[1];        Red7 = LineP2[2]; Blue8 = LineP2[3];        Green8 = LineP2[4];        Red8 = LineP2[5]; if (Blue1 > Blue2) Swap(Blue1, Blue2); if (Blue4 > Blue5) Swap(Blue4, Blue5); if (Blue7 > Blue8) Swap(Blue7, Blue8); if (Blue0 > Blue1) Swap(Blue0, Blue1); if (Blue3 > Blue4) Swap(Blue3, Blue4); if (Blue6 > Blue7) Swap(Blue6, Blue7); if (Blue1 > Blue2) Swap(Blue1, Blue2); if (Blue4 > Blue5) Swap(Blue4, Blue5); if (Blue7 > Blue8) Swap(Blue7, Blue8); if (Blue0 > Blue3) Swap(Blue0, Blue3); if (Blue5 > Blue8) Swap(Blue5, Blue8); if (Blue4 > Blue7) Swap(Blue4, Blue7); if (Blue3 > Blue6) Swap(Blue3, Blue6); if (Blue1 > Blue4) Swap(Blue1, Blue4); if (Blue2 > Blue5) Swap(Blue2, Blue5); if (Blue4 > Blue7) Swap(Blue4, Blue7); if (Blue4 > Blue2) Swap(Blue4, Blue2); if (Blue6 > Blue4) Swap(Blue6, Blue4); if (Blue4 > Blue2) Swap(Blue4, Blue2); if (Green1 > Green2) Swap(Green1, Green2); if (Green4 > Green5) Swap(Green4, Green5); if (Green7 > Green8) Swap(Green7, Green8); if (Green0 > Green1) Swap(Green0, Green1); if (Green3 > Green4) Swap(Green3, Green4); if (Green6 > Green7) Swap(Green6, Green7); if (Green1 > Green2) Swap(Green1, Green2); if (Green4 > Green5) Swap(Green4, Green5); if (Green7 > Green8) Swap(Green7, Green8); if (Green0 > Green3) Swap(Green0, Green3); if (Green5 > Green8) Swap(Green5, Green8); if (Green4 > Green7) Swap(Green4, Green7); if (Green3 > Green6) Swap(Green3, Green6); if (Green1 > Green4) Swap(Green1, Green4); if (Green2 > Green5) Swap(Green2, Green5); if (Green4 > Green7) Swap(Green4, Green7); if (Green4 > Green2) Swap(Green4, Green2); if (Green6 > Green4) Swap(Green6, Green4); if (Green4 > Green2) Swap(Green4, Green2); if (Red1 > Red2) Swap(Red1, Red2); if (Red4 > Red5) Swap(Red4, Red5); if (Red7 > Red8) Swap(Red7, Red8); if (Red0 > Red1) Swap(Red0, Red1); if (Red3 > Red4) Swap(Red3, Red4); if (Red6 > Red7) Swap(Red6, Red7); if (Red1 > Red2) Swap(Red1, Red2); if (Red4 > Red5) Swap(Red4, Red5); if (Red7 > Red8) Swap(Red7, Red8); if (Red0 > Red3) Swap(Red0, Red3); if (Red5 > Red8) Swap(Red5, Red8); if (Red4 > Red7) Swap(Red4, Red7); if (Red3 > Red6) Swap(Red3, Red6); if (Red1 > Red4) Swap(Red1, Red4); if (Red2 > Red5) Swap(Red2, Red5); if (Red4 > Red7) Swap(Red4, Red7); if (Red4 > Red2) Swap(Red4, Red2); if (Red6 > Red4) Swap(Red6, Red4); if (Red4 > Red2) Swap(Red4, Red2); LinePD[0] = Blue4; LinePD[1] = Green4; LinePD[2] = Red4; LineP0 += 3; LineP1 += 3; LineP2 += 3; LinePD += 3; } } } }

  看上去代碼的行數多了,但是實際上執行速度回更快,我們測試的結果如下:

  1920*1080大小的24位圖像,平均用時155ms,灰度圖像平均用時45ms,比之前的原始實現速度要快了近10倍。

   而在任意半徑中值濾波(擴展至百分比濾波器)O(1)時間複雜度算法的原理、實現及效果一文中的算法,採用了SSE優化,同樣大小的圖耗時為:

       1920*1080大小的24位圖像,平均用時260ms,灰度圖像平均用時160ms,比上述的C語言版本要慢。

  早期有朋友曾提示我在手機上使用Neon可以做到16MB的圖像半徑為1的中值模糊可以做到20ms,我真的一點也不敢相信。總覺得不太可思議。16MB可是4000*4000的大小啊,我用上述C的代碼處理起來要242ms,比手機端還慢了10倍。

  經過朋友提醒,在https://github.com/ARM-software/ComputeLibrary/blob/master/src/core/NEON/kernels/NEMedian3x3Kernel.cpp#L113上看到了相關的Neon代碼,驚奇的發現他和我上面的C代碼幾乎完全一樣。但是就是這一點代碼提醒了我。

inline void sort(uint8x8_t &a, uint8x8_t &b) { const uint8x8_t min = vmin_u8(a, b); const uint8x8_t max = vmax_u8(a, b); a = min; b = max; }

  真是一語驚醒夢中人啊,這麼簡單的優化我怎麼沒想到呢。 

  我們自己看看上面的C代碼,每個像素的9次比較雖然不能用SIMD指令做,但是多個像素的比較之間是相互不關聯的,因此,這樣我就可以一次性處理16個像素了,改成SSE優化的方式也就很簡單了:

inline void _mm_sort_ab(__m128i &a, __m128i &b) { const __m128i min = _mm_min_epu8(a, b); const __m128i max = _mm_max_epu8(a, b); a = min;        b = max; } void MedianBlur3X3_SSE(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride) { int Channel = Stride / Width; int BlockSize = 16, Block = ((Width - 2)* Channel) / BlockSize; for (int Y = 1; Y < Height - 1; Y++) { unsigned char *LineP0 = Src + (Y - 1) * Stride + Channel; unsigned char *LineP1 = LineP0 + Stride; unsigned char *LineP2 = LineP1 + Stride; unsigned char *LinePD = Dest + Y * Stride + Channel; for (int X = 0; X < Block * BlockSize; X += BlockSize, LineP0 += BlockSize, LineP1 += BlockSize, LineP2 += BlockSize, LinePD += BlockSize) { __m128i P0 = _mm_loadu_si128((__m128i *)(LineP0 - Channel)); __m128i P1 = _mm_loadu_si128((__m128i *)(LineP0 - 0)); __m128i P2 = _mm_loadu_si128((__m128i *)(LineP0 + Channel)); __m128i P3 = _mm_loadu_si128((__m128i *)(LineP1 - Channel)); __m128i P4 = _mm_loadu_si128((__m128i *)(LineP1 - 0)); __m128i P5 = _mm_loadu_si128((__m128i *)(LineP1 + Channel)); __m128i P6 = _mm_loadu_si128((__m128i *)(LineP2 - Channel)); __m128i P7 = _mm_loadu_si128((__m128i *)(LineP2 - 0)); __m128i P8 = _mm_loadu_si128((__m128i *)(LineP2 + Channel)); _mm_sort_ab(P1, P2); _mm_sort_ab(P4, P5); _mm_sort_ab(P7, P8); _mm_sort_ab(P0, P1); _mm_sort_ab(P3, P4); _mm_sort_ab(P6, P7); _mm_sort_ab(P1, P2); _mm_sort_ab(P4, P5); _mm_sort_ab(P7, P8); _mm_sort_ab(P0, P3); _mm_sort_ab(P5, P8); _mm_sort_ab(P4, P7); _mm_sort_ab(P3, P6); _mm_sort_ab(P1, P4); _mm_sort_ab(P2, P5); _mm_sort_ab(P4, P7); _mm_sort_ab(P4, P2); _mm_sort_ab(P6, P4); _mm_sort_ab(P4, P2); _mm_storeu_si128((__m128i *)LinePD, P4); } for (int X = Block * BlockSize; X < (Width - 2) * Channel; X++, LinePD++) { // DO Something
 } } }

  注意到上面我已經把灰度和彩色圖像的代碼寫成同一個方式處理了,這是因為對於彩色圖像,3個通道之間的處理時毫無聯繫的。同時我們前面的Swap2個變量的過程時完全可以通過Min和Max兩個算子實現的,我們按下F5測試運行,驚人的速度出現了:

       1920*1080大小的24位圖像,平均用時3ms,灰度圖像平均用時1ms,比上述的C語言版本快了近40倍。

       順便也測試了下16MB的圖像,結果平均只需要7.5ms。真是太厲害了。

二、5*5中值模糊

      對於5*5的中值模糊,優化的方式還是一樣的,但是5*5共計25個像素,理論上需要131次比較,其他的過程類似,測試基於SSE的方式,5*5的中值1920*1080大小的24位圖像,平均用時40ms,灰度圖像平均用時20ms,雖慢了很多,但是還是O(1)那裡的速度快。

三、蒙塵和划痕

     在這裏提Photoshop的這個算法也許並不是很合適,但是我也是在研究中值模糊時順便把這個算法給攻破的,當我們打開蒙塵和划痕界面時,發現其有半徑和閾值兩個參數,細心比價,如果閾值設置為0,則相同半徑設置時其結果圖像和雜色里的中間值算法的結果一模一樣,這也可以從蒙塵和划痕算法和中間值同樣都放在雜色菜單下可以看出端倪。   

                     

    通過上述分析,我們可以肯定蒙塵和划痕算法是基於中值模糊的,實際上,PS里很多算法都是基於中值模糊的,特別是那些有平滑度參數的算法^_^。經過多次測試,我們得到的該算法的結果就是如下:

    if  (Median – Src) > Threshold 

    Dest = Median

    else 

    Dest = Src

     對於彩色圖像,不是用彩色圖的中值,而是用其亮度值作為唯一的判斷標準,如果用彩色的中值作為標準來判斷每個分量的,很容易出現過多的噪點,因為有可能會出現Blue分量改變,而Red不變的情況,或其他類似現象。

          蒙塵和划痕的一個作用是去除噪點,特別的,我覺得他在小半徑的時候更為有用,小半徑中值不會改變原圖太多,加上這個閾值則可以很容易去除噪點,同時,基本不會出現新的模糊問題。比如下面這個圖。

        

                           原圖                                                                                                                                                   半徑為1的中值模糊 

        

                                   半徑為1,閾值取20時的蒙塵和划痕                                                                                                            半徑為2,閾值取20時的蒙塵和划痕            

   由以上幾圖,可以明顯的看出,帶閾值的蒙塵和划痕在抑制了噪音的同時對原圖其他細節基本沒有破壞,因此,是一種比較合適的初級的預處理算法,既然是預處理,那麼其效率就非常重要了,因此本文的快速3*3模糊的作用也就是相當有用。

        本文相關算法代碼下載地址:https://files.cnblogs.com/files/Imageshop/MedianBlur3X3.rar。 

   本人的SSE算法優化合集DEMO:測試Demo:http://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar。

       

      

【精選推薦文章】

如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

想要讓你的商品在網路上成為最夯、最多人討論的話題?

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師"嚨底家"!!