@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

指標的藝術

指標的藝術,就是就如同是內功心法一樣,一般程式師只懂的其意,但使用時,如同武學一樣,懂得門面上的套路,卻不一定懂的如何去運用。

何謂指標?就是用來記錄"位址"的變數,或者想像它的值是用來指向某個空間。例如:

int a;
int *b = &a;

b記錄的便是變數a所在空間的位址,也就是指向變數a所在的地方。因此*b=10的結果,便是將10填入b所指的地方,也就是變數a的實體空間裡,其結果跟a=10是一樣的。

void* p;

這樣的寫法表示,p指向的是一個空間,但這個空間裡記錄的是什麼結構並不知道。因此在不知指向的空間是什麼結構前,你無法直接填值進去,必須另外轉型才行。

char** p;

這樣的話,p指向的空間裡,是記錄char*這樣的結構 (也就是再記錄一個位址值)。因此*p存取到的,都是位址值。取到位址值後,必須再指向一次,才能得到實際的空間。也就是**p才是指向記錄char這個結構的空間。

陣列變數其實也可以視為指標來看待:

int p1[10];
int *p2 = p1;

p1與p2指向的空間位址都是一樣的,只不過p1可以知道是一個連續10個int空間的陣列。p2的話,只知道是指向一個記錄int的空間,是不是陣列則是程式師才知道。在這個例子中,因為已經知道p2指向的是一個int陣列,所以可以用p2[5]這樣的方式來存取陣列內容。或者也可以寫成*(p2+5),它的意義則是p2指向的位址再往下5個結構,然後存取裡面的值。因為p2是指向的空間裡,記錄的是int結構,所以再往下5個int便是第6個int空間,跟p2[5]是相同的。

int p1[10][20];
int **p2;

二維以上的陣列與指標就不太一樣,p1是指向一個一大塊的空間,這個空間被規劃成10×20個int。p2則是指向一個int*的空間。然後再從該空間裡記錄的位址再去存取實際的內容,這種方法為間接存取。假設p2是被做成跟p1一樣10×20維度的陣列,那麼p2在空間的運用上也與p1不同。因為p1指向的空間是一整塊,維度也是已知 (必須是已知)。所以p1[i][j]馬上可以知道是在記錄空間裡的那一個地方。但p2就不同了,p2必須是先指向一個int*[10]的空間,每個空間分別指向int[20]的空間,因此實際的空間並非一大塊,而是拆成11個 (其中一個是用來存放其他空間的位址用的)。因此p2[i][j]實際上是先p2[i]從int*[10]空間裡取到指標值, 然後再經由這個指標值再做[j]得到實際的空間, 然後進行存取。

但是一般人會認為指標好處是節省記憶體。指標的好處不是節省記憶體,大部份的情況反而比較浪費記憶體。但指標的目的,多半是彈性的處理,特別是不知道資料量大小的情況下,往往必須使用動態記憶體,此時便需要配合指標來處理。

如下兩種方式宣告,但是目的都只是放數值:
int *p;
*p=1;

int p;
p=1;
上面範例大部分還是使用int p

那怎樣是使用指標的時機呢?
如同上面範例p是用來指向一個int空間, 但沒給初值,也就是不知指向那裡,因此將1存入不知那個地方,一定會出問題。指標變數本身的空間 (也是有佔用空間唷),是用來記錄位址,所以填入p的值必須是某個空間的位址,在p沒指向一個切確的空間前,是不能去存取它指向的空間內容。即使有指向某個空間,也要看該空間還是否合法,像指向的動態記憶體被釋放掉了,或是指向的區域變數已離開它所在的scope等,這時原指向的空間已消失,再去存取,常會造成問題。

int p;
p=1;

這樣的變數p,本身空間是一個整數,因此存取的,都是整數值。

每個變數宣告後,都會佔用一定的空間,至於佔用多少空間、存取的內容是什麼,便視變數的形態而定。範例中int*p; p佔用sizeof(int*)空間,存取的內容是int*結構的位址值。int p; p佔用sizeof(int)空間,存取的內容是int結構的整數值。

雖然這些都是基本的觀念,但仍然要多用不同的寫法去體悟箇中意境,才能了解指標是如何使用。

原文出處:http://m.blueshop.com.tw/Thread.aspx?tbfumsubcde=BRD20141226210510PQJ

相關閱讀:http://nkeys.logdown.com/posts/472329-c-memory-configuration

http://nkeys.logdown.com/posts/472926-c-memory-configuration-continued

[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/資料夾下

深入理解JDBC的超時設置

文章來源 http://www.importnew.com/2466.html

使用 Grafana+collectd+InfluxDB 監控系統

http://cyrilwang.blogspot.tw/2016/09/collectd-influxdb-grafana.html

使用 Grafana+collectd+InfluxDB 打造现代监控系统