Spring Cloud學習資源

Spring Cloud中文網:
https://springcloud.cc
https://springcloud.cc/spring-cloud-dalston.html

Spring Boot參考指南:
https://www.gitbook.com/book/qbgbook/spring-boot-reference-guide-zh/
https://qbgbook.gitbooks.io/spring-boot-reference-guide-zh/

Spring Cloud Stream Reference:
http://docs.spring.io/spring-cloud-stream/docs/Chelsea.SR2/reference/htmlsingle/
http://weifuwu.io/2016/09/15/dive-into-spring-cloud-stream/

Spring Cloud Task Reference:
http://docs.spring.io/spring-cloud-task/docs/1.2.0.RELEASE/reference/htmlsingle/

[轉] 軟體工程

文章轉錄自:http://irw.ncut.edu.tw/peterju/se.html

物件導向的塑模 = 軟體架構

軟體開發如同音樂譜曲及建築設計,其過程中必須將需求、分析、設計、實作、佈署等各項工作流程之不同觀點予以呈現,這就是軟體系統之塑模(Modeling)。

Booch等人 / Rational Software 提出可從4+1觀點(4+1 view)來看軟體系統架構(凸顯使用個案的重要性)

  • 使用個案觀點(Use Case View):以使用個案充分表達軟體功能需求
  • 設計觀點(Design View):以物件的觀念,表達出軟體設計結果 (Logical View)
  • 流程觀點(Process View):
  • 實施觀點(Implementation View)
  • 佈署觀點(Deployment View)

根據上述5個觀點我們可以整理出6種塑模

  • 使用個案塑模:使用個案圖
  • 物件資料結構塑模:類別圖、物件圖
  • 物件互動行為塑模:互動圖(包含了循序圖、合作圖)
  • 作業行為塑模:活動圖、狀態圖
  • 使用者介面塑模:
  • 系統元件與組織結構塑模:元件圖、部署圖

物件導向的軟體維護

  • 軟體的維護就是軟體的再生,維護較開發而言要花更多的金錢與時間
  • 軟體維護的思維上就是要考慮到 可維護性(Maintainability) 可重複使用性(Reuseability)
  • 傳統的重複使用方案並無法兼顧可維護性與可重複使用性的目標,物件導向設計的重複使用方式可在含有宏觀商業邏輯的抽象層次的上層結構來考量,以達到可維護與可重複使用的目標。
  • 物件導向類別設計的法則
    • 開閉原則(Open-Closed Principle ; OCP)
    • Liskov代換原則(Liskov Substitution Principle ; LSP)
    • 依賴倒轉原則(Dependency Inversion Principle ; DIP)
    • 介面隔離原則(Interface Segregation Principle ; ISP)
    • 組合/聚合重複使用原則(Composition / Aggregation Principle ; CARP)
    • Demeter原則(Law of Demeter; LoD)

開閉原則(Open-Closed Principle ; OCP)

  • 模組應當敞開擴充大門,但關閉修改之窗
  • 如何達成開閉原則,關鍵在抽象化。
  • 不允許更改的是系統的抽象層,允許擴充的是系統的實作層。
  • OCP的另一個角度是EVP對可變性的封裝原則(Principle of Encapsulation of Variation)即找到一個系統的可變因素,並將之封裝起來。
  • 可變性必須被封裝,那不同的可變性呢?應用繼承來處理,因此繼承應被視為封裝變化的方法,但繼承的層數避免超過2層以免不同的可變性混和。
  • 應避免將單純的流程控制轉移語句改寫成多型,除非內含了某種商務邏輯。
  • 所有的設計樣式(Design Pattern)都是針對不同的可變性封裝,使系統在不同的角度上達到開閉原則。

Liskov代換原則(Liskov Substitution Principle; LSP)

  • 子類別應該可以使用其基礎類別替代
  • Liskov代換原則是繼承之所以能重複使用的基石,只有當衍生類別可以替換掉基礎類別,且軟體的功能不受影響時,其類別才算真正的被重複使用,而衍生類別也才能夠在基礎類別的基礎上增加新的行為。
  • Liskov代換原則要求凡是基礎類別使用的地方,衍生類別一定適用,故衍生類別必須包含全部基礎類別的介面
  • 針對違反LSP設計時可行的重構(Refactoring)方式
    • 當類別A錯誤的繼承類別B時,可建構一個新的抽象類別C,作為2個具體類別A,B的父類別
    • 當類別A錯誤的繼承類別B時,可重構為類別B委派(Delegate)類別A

依賴倒轉原則(Dependency Inversion Principle; DIP)

  • 要依賴於抽象,而不要依賴於具體
  • 依賴倒轉原則的策略是依賴介面或抽象方法及類別,而不是具體方法或類別,包括了下列情況都得遵循DIP
    • 變數的類別宣告
    • 參數的類別宣告
    • 方法的傳回型態宣告
    • 型態的轉換
  • 抽象層級含有宏觀和重要的商務邏輯,具體層級含有與實作有關的演算法語次要的商業邏輯,而傳統的程序性設計或錯誤的類別規劃會讓抽象層級依賴於具體層級,因此依賴倒轉原則可倒轉此一現象,讓實作改變時,商業邏輯無須變動。
  • 一個具體Java類別應當只實作Java介面和抽象Java類別中宣告的方法,而不應當給出多餘的方法。
  • 若Java程式要參照一個物件,若此物件有一個抽象型態,則應使用此抽象型態作為靜態型態(Static Type)
    • 靜態型態(Static Type) = 實際型態(Apparent Type):變數被宣告時的類別
    • 實際型態(Actual Type):變數所參照的物件真實型態
  • 若一個物件存在其抽象類別,就應當在任何參照此物件的地方使用抽象類別
  • Java語言中建構一個物件的程式是違背OCP與DIP的,但可在此類別被建構出來後過多型性使得使用端依賴於其抽象類別。
    • List employees = new Vector();
  • DIP是最難實作的原則,因為會使用到物件工廠就會產生大量的類別。
  • DIP假定所有的具體類別都是會變化的並不完全正確,因為某些具體類別是相當的穩定因此並不需要為此發明一個抽象型態。

介面隔離原則(Interface Segregation Principle; ISP)

  • 由客戶端指定的許多介面比一個一般用途的介面好。
  • 使用多個專門的介面比使用單一的總介面要好,否則會造成對介面的污染(Interface Contamination)。
  • 一個類別對另一個類別的依賴性應當是建立在最小的介面上的。

組合/聚合重複使用原則(Composition / AggregationPrinciple ; CARP)

Demeter原則(Law of Demeter; LoD)

統一塑模語言(Unified Modeling Language ; UML)

  • 由Rational software corporation融合了物件導向三劍客的方法論,統一了以物件導向分析與設計的表示法,於1997年11月由 OMG(Object Management Group) 公布為物件導向視覺化塑模的標準,目前 最新的版本為 2.0 (2003/06/01)
  • UML是一種塑模語言,而非方法論,它並沒有規範符號的使用時機與次序僅利用符號來達到溝通的目的,從分析,設計到實作都可以使用同一套符號來表達,因此應用時可以搭配適合的方法論。
  • UML之所以重要,就是因為他有助於軟體開發人員之間的溝通。我們必須在某種程度上使用他以協助溝通,而非阻礙溝通。
  • 循序圖、合作圖合稱互動圖。
  • UML設計的理念
    • 使用個案導向(強調以使用者的角度來定義功能需求)
    • 軟體架構設計(強調系統開發要有藍圖)
    • 往覆,漸增式流程(強調降低專案風險)

使用個案圖(Use Case Diagram)

  • 以OO技術開發系統時在需求分析時常利用典型的情節(Scenario)來進行需求塑模,這種個案模式一直沒有統一的表達方式直到Ivar Jacobson等人(1996) 才將使用個案的表達正式化。
  • 使用個案圖表示從使用者之觀點描述系統的行為者與系統間之互動行為與關係,包含了行為者和使用個案二個元件,此法在資料與展示格式上僅利用文字描述,若能搭配結構化中的藍圖與資料詞彙則可補強其不足之處。
  • 使用案例是專業分工的依據,是專案進度評量的重要因素。

行為者(Actor) = 參與者

  • 環境中與系統有互動關係的人或事物,有該使用個案的啟動者即 主要行為者(Primary Actor) 與其他參與者即 次要行為者(Secondary Actor)
  • 參與者被繪製成一個火柴棒形狀的小人並將名稱置其下方。

使用個案(Use Case)

  • 使用者透過介面要求系統所做一系列相關的事件流,包含了最主要的事件即 基本路徑(Basic Course) 與其他衍生事件或可能發生的錯誤即 替代路徑(Alternative Courses)
  • 使用案例被繪製成橢圓形並將名稱置於圖形內部或底部來表示
  • 使用個案間的關係:
    • 關聯(association):使用個案與行為者之間的關係,以實線段表示。
    • 包含(Include):一個使用個案會用到另一個使用個案,二個或以上的使用個案具有相同的行為模式時,可將該段行為模式獨立出來成為一個新的使用個案,再建立包含的關係,用一個虛線實心箭頭的線段並含有關鍵字 <<include>> 。
    • 延伸(Extend):在某情況下,使用個案會插入另一使用個案的定義中,用一個虛線實心箭頭的線段並含有關鍵字 <<extend>> 。
    • 一般化(Generalization):一個使用個案繼承另一個使用個案的行為, 用一個實線空心箭頭表示的線段從子使用個案指向父使用個案,且箭頭朝向父使用個案端。

情節(Scenario)

使用個案中的某一個單一執行路徑,可能是基本路徑也可能是替代路徑。

建構使用個案圖的步驟

  1. 找出行為者:從環境圖找
  2. 找出使用個案:由行為者找出使用個案
  3. 描述使用個案:可用自然語言或事件條列式
  4. 找出使用個案間的關係:
  5. 繪製使用個案圖

類別圖(Class Diagram)

  • 表示系統存在之類別、介面及它們間之靜態資料結構與邏輯關係
  • 通常以三層表示
    • 類別名:正體字:具體類別,斜體字:抽象類別,介面:<interface>
    • 屬性層:
    • 方法層:
  • 屬性與方法有四種封裝方式
    • public:以符號 + 表示
    • private:以符號 表示
    • protected:以符號 # 表示
    • static:以符號 _ 表示
  • 描述介面的類別圖:沒有private的封裝
  • 描述物件的類別圖:描述類別的實體,名稱下需加底線

關係

類別間的關係包括了

  • 依賴 / 相依(Dependency)
    • 使用的關係,表達一個類別會用到另一個類別
    • 另一個類別的改變會影響到使用他的類別,但反之不必然
    • 一類別的區域變數,方法參數,方法返回值,對靜態方法呼叫時是另一個類別時稱之
    • 以虛線開箭頭表示。——->
  • 一般化(Generalization)
    • 繼承的關係,包括了類別間的繼承,介面間的繼承,類別對介面的實作等
    • 以實線空心箭頭表示。
  • 關聯/結合(Association)
    • 同一層級的類別間靜態的結構關係
    • Java語言中是使用實體屬性實作的
    • 其關係有雙向與單向,建議多用單向
    • 關係有基數(Multiplicity),關係有名稱,但通常均予以省略
    • 以實線段表示。 —
      • 依關聯的類別個數來分
        • 二元關聯(Binary Association)
        • 多元關聯(n-ary Association)
      • 依描述整體與部分的關係來分(不同層級的類別)
        • 聚合 / 聚集(Aggregation):以實線且整體端加一個空心的菱形表示。◇—
        • 合成 / 組合(Composition):整體物件需負責部分物件的生命週期,以實線且整體端加一個實心的菱形表示。◆—
  • 實現化(Realization)
    • 以介面實現其他類別之描述
    • 以虛線空心箭頭表示。

基數(Multiplicity) =多重性

在類別連線上與類別之旁以數字標示與之關聯的數量。

物件圖(Object Diagram)

  • 描述系統於某一時間點的靜態結構,也稱為案例圖,包含了物件與連線二個元件。物件間的關係稱為連線(Link)。

循序圖(Sequence Diagram)

  • 以時間發生之先後順序來表達物件間的訊息傳遞與處理之程序,包含了類別之物件、訊息、操作、生命線與控制焦點等元件。
  • 循序圖有2個象線
    • 垂直象線依照訊息呼叫發生的時間順序,來描述訊息呼叫的先後次序。
    • 水平象線描述一個物件實體傳送訊息給哪一個物件實體。

訊息(Message) =刺激(Stimuli)

由某一物件傳送訊息至另一物件以啟動操作,以上下位置表示順序。

生命線(Lifeline)

表達物件再某時段的存在,以物件下與物件垂直之虛線表示。

控制焦點 (Focus of Control) =啟動條(ActivationBar)

表達物件執行某動作之時段,與生命線重疊且以高瘦的矩形表示。

系統邊界 (System Border)

系統與外界溝通之介面,通常放置在循序圖的最左側。

建構循序圖的步驟

  1. 確認物件
  2. 描述操作
  3. 描述訊息
  4. 繪製循序圖

合作圖(Collaboration Diagram)

  • 著重表達物件間之連結結構,並能同時展現物件間的訊息傳遞與處理之程序,包含了類別之物件、連結、訊息與操作等元件。
  • Rational Rose可將循序圖直接轉換成合作圖。
  • 合作圖與循序圖相比較,少了物件生命線與焦點控制,多了路徑與序數

連結(Link)

以直線連接二個物件也就是物件間的路徑(Path)。

訊息(Message)

訊息發生順序以自然數或杜威數等編號來表達。

活動圖(Activity Diagram)

狀態圖(State Diagram)

元件圖(Component Diagram)

部署圖(Deployment Diagram)

Apache Storm介紹

http://www.cnblogs.com/Jack47/p/storm_intro-1.html

http://ifeve.com/getting-started-with-storm-1/
http://ifeve.com/getting-started-with-storm-2/
http://ifeve.com/getting-started-with-storm-3/
http://ifeve.com/getting-started-with-storm-4/
http://ifeve.com/getting-started-with-storm-5/
http://ifeve.com/getting-started-with-storm6/
http://ifeve.com/getting-started-with-storm7/
http://ifeve.com/getting-started-of-storm8/

http://ifeve.com/author/onenote/

@Transactional 參數小技巧

1. DAO層get method最好都設定成readOnly=true, 預設值是false
2. synchronized不要加在DAO層, 應加在Service層
3. 如果synchronized method有@Transactional, 務必設定timeout

Spring Propagation types

Spring交易的屬性介紹

https://openhome.cc/Gossip/SpringGossip/TransactionAttribute.html

Propagation behavior:

MANDATORY
Support a current transaction, throw an exception if none exists.

Does not start a new Transaction, just checks whether a transaction is active (must be inside either another @Transactional method call or a programmatically created transaction)

NESTED
Execute within a nested transaction if a current transaction exists, behave likePROPAGATION_REQUIRED else.

Start a nested transaction if a transaction exists, start a new transaction otherwise.

NEVER
Execute non-transactionally, throw an exception if a transaction exists.

Does not start a transaction. Fails if a transaction is present.

NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists.

Does not start a transaction. Suspends any existing transaction.

REQUIRED
Support a current transaction, create a new one if none exists.

If a transaction exists, use that, if not, create a new one. In 95% of cases, this is what you need.

REQUIRES_NEW
Create a new transaction, suspend the current transaction if one exists.

Always creates a new transaction, no matter if an existing transaction is present. If there is, it will be suspended for the duration of this method execution.

SUPPORTS
Support a current transaction, execute non-transactionally if none exists.

Can use a transaction if one is present, but doesn’t need one (and won’t start a new one either)

tomcat 遠端監控

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port={port for access}
-Dcom.sun.management.jmxremote.rmi.port={port for access}
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname={optional, bind IP}

init.d 加完以上JVM參數就可以用visualvm遠端監控了

Tomcat出現大量CLOSE_WAIT

最近遇到tomcat出現大量CLOSE_WAIT的問題, 始終找不出原因
以下是TCP連線的步驟

CLIENT                                 SERVER

1.    ESTABLISHED                    ESTABLISHED
2.    (Close)
FIN-WAIT-1  –> <FIN,ACK>  –> CLOSE-WAIT
3.    FIN-WAIT-2  <– <ACK>      <– CLOSE-WAIT
4.                                   (Close)
TIME-WAIT   <– <FIN,ACK>  <– LAST-ACK
5.    TIME-WAIT   –> <ACK>      –> CLOSED
(2 MSL)

Server端出現CLOSE_WAIT表示Server"被動地"收到關閉連線通知,Server確實關閉socket連線後會發LAST_ACK回去給Client端
通常CLOSE_WAIT出現的時間很短暫,會出現大量CLOSE_WAIT有以下幾種可能:
1. CPU資源吃緊,該請求正排隊關閉連線:此為正常現象,通常一段時間後就會消失,建議換好一點的硬體設備
2. 後端code有無窮迴圈,Server無法回應該請求:基本上這種情況可以排除,通常這類有明顯bug的code很快就會被發現,除非是天兵工程師。可用jstack或visualvm等工具查看
3. 後端code的multi-thread發生deadlock,Server無法回應該請求:檢查程式有synchronized的地方,可用jstack或visualvm等工具查看
4. 後端code有直接對Remote端發TCP packet的地方沒正確關閉連線:當Server的後端code用client類別連到Remote端,連線逾時遭到Remote端斷線,此時被動關閉連線時,code若沒處理好關閉,就會造成本地端CLOSE_WAIT
5. 某一版Tomcat或JVM的bug造成無法關閉socket

—-
問題發生原因:
http://jschu.blog.51cto.com/5594807/1732414

http://m.myexception.cn/open-source/921974.html

http://serverfault.com/questions/160558/how-to-not-get-so-many-apache-close-wait-connections

http://ahuaxuan.iteye.com/blog/657511

暴力刪除法:
https://github.com/rghose/kill-close-wait-connections

https://www.experts-exchange.com/questions/20568402/How-to-clear-CLOSE-WAIT-state-of-a-TCP-connection.html

http://www.shellhacks.com/en/HowTo-Kill-TCP-Connections-in-CLOSEWAIT-State

HTTP的session, cookie和connection

Session: server端記載的用戶會話清單, 存在server記憶體, 可以視為server端的cookie, 以session-id辨認用戶端。session的expired time由web app設定的timeout決定, 一旦用戶存取server就重新計時, 若用戶閒置超過timeout時間就會把該用戶從會話清單移除掉 [現實對照: 某一天的聊天對象]

Cookie: client端的屬性資訊, 例如session cookie就記載著用戶的session-id。cookie可以存成file, 也可以設定cookie expired的期限。若是session cookie就無法存成file, 關閉瀏覽器cookie就消毀;若有HttpOnly flag的cookie只能透過Http(s)存取, Javascript不能存取。[現實對照: 某個聊天對象是誰, 及他的嗜好興趣]

Connection: 指server與client溝通時建立的TCP socket連線。當瀏覽器連到某個web server時, 瀏覽器會帶Connection: keep-alive的表頭, 告訴server端保持連線, 此時server就會開著一條與該client溝通的socket連線, 直到關閉瀏覽器或client端發出"Connection: close"的表頭, 抑或是閒置太久由server端斷開便會中止連線。(注意: curl的Connection表頭永遠是close, 就算加上-H “Connection: keep-alive"也沒用;telnet的Connection表頭預設是keep-alive, 但是可以透過更改Connection: close來斷開連線) [現實對照: 某一次的通話]

[轉] How To: ICMP Ping in Java (JDK 1.5 and above)

Programatically using ICMP Ping is a great way to establish that a server is up and running. Previously you couldn’t do ICMP ping (what ping command does in Linux/Unix & Windows) in java without using JNI or exec calls. Here is a simple and reliable method to do ICMP pings in Java without using JNI or NIO.


String host = "172.16.0.2"
int timeOut = 3000; // I recommend 3 seconds at least
boolean status = InetAddress.getByName(host).isReachable(timeOut)

status is true if the machine is reachable by ping; false otherwise. Best effort is made to try to reach the host, but firewalls and server configuration may block requests resulting in a unreachable status while some specific ports may be accessible. A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

In Linux/Unix you may have to suid the java executable to get ICMP Ping working, ECHO REQUESTs will be fine even without suid. However on Windows you can get ICMP Ping without any issues whatsoever.

PS: Linux 版必須該 JVM 使用者有 root 權限發 ICMP

[Xcode][UE4] 拯救無法開啓的UE4專案

1. 到UE專案目錄下, 刪除 Intermediate, Binaries目錄
2. 在.uproject檔案按右鍵 -> 服務 -> Generate Xcode Project
3. 打開 .xcworkspace檔案, 在Xcode的Build/Stop(播放/停止圖示)旁有個Set the active schema(圓規圖示), 選自己的專案
4. 再點一次圓規圖示 -> Edit Schema -> 將所有Build Configuration都從Development Editor換成Development
5. 在Xcdoe Build Sccuess後, 便可用Unreal Editor打開專案

在Xcode中匯入Source檔案:
1. 在Games/專案檔按右鍵 -> Add Files to “專案"… -> 選擇檔案 -> 下面Add to targets要勾XXX_index
2. 打開Xcode右側欄, 匯入後的檔案Location是Relative to Group, 改成Relative to Project
3. 將檔案拖曳到Games/專案檔/Source/資料夾下