因為 Spring Data JPA 用來存取資料庫時很方便,然後 DynamoDB 又是屬於特別囉唆的東西,所以之前在研究 Spring Boot 時,就在想不知道 Spring 是否有支援 DynamoDB 的實作。很幸運地,社群真的有人做了 Spring Data JPA + DynamoDB [1-2] 造福大家!XD
Software entities (class, modules, functions, etc.) should be open for extension, but closed for modification. Junior programmers create simple solutions to simple problems. Senior programmers create complex solutions to complex problems. Great programmers find simple solutions to complex problems. 註1:本部落格的範例程式碼在 2015 年以前的文章中,大多是以全型空白做縮排。如需服用,請自行用文字編輯器的取代功能把全型空白取代成半型空白。
- Bertrand Meyer
- Charles Connell
註2:本部落格的內容授權請參閱部落格底部的授權宣告。
2018年5月21日 星期一
2018年5月17日 星期四
在 GCP 上為 VM 設定防火牆
在雲端環境中,防火牆的概念其實跟傳統模式有點不同。傳統的防火牆概念是在作業系統上設定像是 iptables 等。但在雲端上,因為網路服務是由獨立的元件提供的,所以其實應該用 SdN(Software defined Network)的方式來思考這個問題。具體來說就是,網路相關的設定並不會在 VM 上設定,而是在 VM 外部設定,就像是真的有個牆放在 VM 前面這樣。
設定防火牆規則
在 GCP 中,網路服務的提供是由 VPC 來進行的,因此在設定時要先在「VPC networks」裡的「Firewall rules」新增防火牆規則。防火牆規則的內容中,最重要的在於這個規則要套用到哪些 VM,而決定套用對象的方式在於設定「Targets」。
Targets 有三種模式可以設定:
- All instances in the network
- Specified target tags
- Specified service account
如果想要簡單的話,可以設定成 1,也就是規則將套用到網路中所有的 VM。不過如果只想針對特定一些 VM 的話,用 2 比較合適。用 2 的模式時,會需要輸入對象的標籤名稱,假設我想要打開 22 port,所以我命名標籤叫做「allow-ssh」,代表只要 VM 有「allow-ssh」這個標籤,就要套用這條防火牆規則。
設定 VM 標籤
接下來是比較奇特的地方,在 VM 上要標剛剛寫的標籤。從「Compute Engine」進入「VM Instances」,然後編輯想要設定防火牆的 VM。編輯時,要注意要找的是「Network tags」(中文介面會寫「網路標籤」)而不是「Lables」(中文介面會寫「標籤」)……。因為剛剛在防火牆規則設定的標籤是「allow-ssh」,因此 VM 的 Network tags 裡也要設定相同的名字。設定完以後,儲存然後稍微等一下下,防火牆規則就會套上 VM 了。
2018年5月15日 星期二
Ethereum 基礎概念與原理
Ethereum 是一種分散式帳本的技術,雖然說大家更熟知的是「以太幣」這個虛擬貨幣~。不過這裡會嘗試從系統工程師的角度來看帶這個技術。
這篇文章大概會寫得有點雜亂,因為這主要是要紀錄一些本來我自己不太清楚的問題。如果需要比較完整、有條理的說明,推薦可以認真看看 [1]。
2018年5月11日 星期五
2018年5月7日 星期一
AWS DynamoDB SDK v2 基礎使用(四):讀取資料
在 DynamoDB 中,讀取被分成 Query 和 Scan 兩種行為
兩種行為的差異,主要來自於存取的範圍是否侷限於同一個 Partition。
這其實在之前(好久以前了呀….XD)的文章中有提到過,概念上可以當成一個 Partition 就是一台主機
在寫入資料時,作為 Partition Key 的值會決定資料會被存放在哪一台主機。
而讀取資料時,使用 Query 是在特定一台主機上讀取資料,而使用 Scan 則會在所有主機上讀取資料。
2018年4月24日 星期二
Logback 的 Log 篩選設定
平常比較容易遇到的有幾種案例:
- 我想要 logback 輸出所有的 log,但特定某些 package 想要隱藏 DEBUG 和 TRACE
- 我想要 logback 只輸出 INFO 以上的 log,但特定某些 package 想要輸出所有 log
- 我想要 logback 只輸出 INFO 以上的 log,但特定某些 package 想要輸出所有 log,而且某個 package 的 INFO 以上 log 要輸出到別的 appender
之前開發時,大多用到的是第一種,但偶而想要第二和第三種時,花了不少時間才調整出來
最後發現一開始對設定的認知其實有點不太正確。
2018年4月13日 星期五
2018年4月11日 星期三
Spring Data JPA 的 JOIN 操作
其實在 Spring 上要做 JOIN,還挺麻煩的…
如果可以的話,我覺得能不要做就不要做比較好 XD
不過真的需要的時候,如果是需要 SELECT 時做 JOIN,推薦可以參考 [1-2] 的說明。
實務應用的話,假設以 logback 輸出到 SQL Server 的格式作為範例
想要一次取得整個 log 包含相關的 property 和 stack trace,以下的 Entity 範例是能夠套用。
logback 輸出 SQL Server 的 schema
schema 可以參考 [3],以下為 schema 的內容:
CREATE TABLE logging_event
(
timestmp DECIMAL(20) NOT NULL,
formatted_message VARCHAR(4000) NOT NULL,
logger_name VARCHAR(254) NOT NULL,
level_string VARCHAR(254) NOT NULL,
thread_name VARCHAR(254),
reference_flag SMALLINT,
arg0 VARCHAR(254),
arg1 VARCHAR(254),
arg2 VARCHAR(254),
arg3 VARCHAR(254),
caller_filename VARCHAR(254) NOT NULL,
caller_class VARCHAR(254) NOT NULL,
caller_method VARCHAR(254) NOT NULL,
caller_line CHAR(4) NOT NULL,
event_id DECIMAL(40) NOT NULL identity,
PRIMARY KEY(event_id)
)
CREATE TABLE logging_event_property
(
event_id DECIMAL(40) NOT NULL,
mapped_key VARCHAR(254) NOT NULL,
mapped_value VARCHAR(1024),
PRIMARY KEY(event_id, mapped_key),
FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
)
CREATE TABLE logging_event_exception
(
event_id DECIMAL(40) NOT NULL,
i SMALLINT NOT NULL,
trace_line VARCHAR(254) NOT NULL,
PRIMARY KEY(event_id, i),
FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
)Entity
假設我的 Entity 物件名字是 Activity、ActivityProperty、ActivityStackTrace,分別定義如下:
Activity
@Entity(name = "logging_event")
public class Activity implements Serializable {
@Id
@Column(name = "event_id")
private Long eventId;
@Column(name = "timestmp")
private Long timestmp;
@Column(name = "formatted_message")
private String message;
@Column(name = "logger_name")
private String logger;
@Column(name = "level_string")
private String level;
@Column(name = "thread_name")
private String thread;
@Column(name = "reference_flag")
private Integer reference;
@Column(name = "arg0")
private String arg0;
@Column(name = "arg1")
private String arg1;
@Column(name = "arg2")
private String arg2;
@Column(name = "arg3")
private String arg3;
@Column(name = "caller_filename")
private String callerFile;
@Column(name = "caller_class")
private String callerClass;
@Column(name = "caller_method")
private String callerMethod;
@Column(name = "caller_line")
private String callerLine;
@OneToMany(
mappedBy = "eventId",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER)
private List<ActivityProperty> properties;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "event_id", referencedColumnName = "event_id")
@LazyCollection(LazyCollectionOption.FALSE)
private List<ActivityStackTrace> stackTraces;
}ActivityProperty
@Entity(name = "logging_event_property")
public class ActivityProperty implements Serializable {
private static final long serialVersionUID = -6532428503805543364L;
@Id
@Column(name = "event_id")
private Long eventId;
@Column(name = "mapped_key")
private String key;
@Column(name = "mapped_value")
private String value;
}ActivityStackTrace
@Entity(name = "logging_event_exception")
public class ActivityStackTrace implements Serializable {
private static final long serialVersionUID = -50856985039937262L;
@EmbeddedId
private ActivityStackTraceId id;
@Column(name = "trace_line")
private String line;
}ActivityStackTraceId
@Embeddable
public class ActivityStackTraceId implements Serializable {
private static final long serialVersionUID = -4496556483758827756L;
@Column(name = "event_id")
private Long eventId;
@Column(name = "i")
private Integer i;
}其中在 Activity 要連結 ActivityProperty 和 ActivityStackTrace 時,都是以 @OneToMany 來標注
用來表示一個 Activity 可以有多個 ActivityProperty 和 ActivityStackTrace。
此外,由於 ActivityStackTrace 並非是單一 ID,而是 Composite Primary Key 的形式
因此要利用 @Embeddable來組合。這部份可以參考 [4]。
同時,使用了 @Embeddable 之後,如果 JOIN 操作依然使用 mappedBy 的話,會出現 [5] 提到的錯誤
目前其實還沒有搞很懂這個錯誤是什麼意思,不過姑且使用 [5] 的作法,改成用 LazyCollection 可以解決。
未來如果有把問題搞懂的話,再回來追加補充了 @@a
除此之外,還得稍微注意一下,上述的 JOIN 寫法,有可能導致 [6] 描述的問題
也就是當要做資料刪除時,Hibernate 產生的 SQL Statement 會用很沒效率的方式在刪除關聯
而且某些狀況下有可能會刪除沒有預期要刪除的資料。