2019/04/23

獨角獸與承諾思維

從未來地圖一書中得到的概念

獨角獸

  • 讓人思考未來會怎樣
  • 使人自然改變自己
  • 創造社會價值


承諾思維 (Thinking in Promises):以終為始來思考如何做事

2019/01/16

以Python程式產生InfluxDB資料

我們接下來將寫個Python程式,來模擬溫度sensor產生資料並寫入InfluxDB中。然後利用這些資料,在Chronograf中設定dashboard的樣式。

要讓Python連上InfluxDB,我們需要Python-InfluxDB connection。我們可以使用pip來安裝這個connection元件:"pip install influxdb"。詳細指令介紹可參考這一頁。(此範例使用的是Python 3.x)

接下來的程式是模擬廚房、臥室、客廳三個溫度感應器,每秒鐘會回報溫度到InfluxDB。程式一開始,會先建立與InfluxDB server的連結,並建立一個 "sample"的database。我們準備了一個obj的json物件樣板。大家可以把measurement想像成表格(table)名稱。這裡有兩個columns,一個是location用來存放感應器位置,另一個是value來存放溫度。前面有提過,tag是indexed column,field是non-indexed column。由於InfluxDB是時間序列資料庫,因此每筆資料都隱含了一個time的column。

開始執行此Python程式後,就可以看到InfluxDB視窗一直有log message在跑,如果沒有error message,就表示此python程式正在餵資料到InfluxDB。




from influxdb import InfluxDBClient
import random
import time

host = "localhost" #influxdb IP
port = 8086 #influxdb port
username = "root" #influxdb username
password = "root" #influxdb password
dbname = "sample" #database name

# json object template
obj = {'measurement':'temperature', 'tags':{'location':''}, 'fields':{'value':0}}

# arrays for location names and temperatures
locations = ['kitchen', 'bedroom', 'living room']
t = [20] * len(locations)

client = InfluxDBClient(host, port, username, password) # connect influxdb
client.create_database(dbname) # create database

while True:
 for i in range(0,len(locations)):
  t[i] = round(t[i] + random.uniform(-0.5, 0.5), 2) # generate temperature

  # prepare data object
  obj['tags']['location'] = locations[i]
  obj['fields']['value'] = t[i]
  print(obj)

  # write data to influxdb
  client.write_points([obj], 'ms', dbname)

 time.sleep(1)


Python-InfluxDB connection元件的相關資料,可參考這頁的說明。

我們可以把InfluxDB client開啟,打入下列指令,來看最近三秒寫入InfluxDB的資料,確認資料確實有寫入。從這裡我們也可看到,除了location與value這兩個我們設定的欄位外,還有一個time欄位。

接著我們再用瀏覽器進入Chronograf網頁介面。(http://localhost:8888)
我們到Dashboard這頁,可以看到下面的畫面。

點選line,然後add data,接下來都可以用點選的方式來產生dashboard圖樣。我們先產生一個彙總的圖表。點選sample,再點選temperature,把三個地點都勾起來,並點選group by location,然後再把value勾起來。這個操作過程會自動幫我們產生InfluxQL。完成後點選右上角的綠色勾即可儲存。

回到Dashboard頁面,可以設定此圖表之位置與大小,並可在右上角設定更新速度與資料顯示長度。

正上方有Add a Cell to Dashboard藍色按鈕,可以加入更多圖表。大家可以去玩玩各種圖表,了解Chronograf。Chronograf的使用說明可以參考官網的文件


InfluxDB

若想了解時間序列資料,可參考這篇簡述
InfluxDB應該是目前佔有率最高的TSDB了,因此我們利用InfluxDB來了解TSDB的運作。

這裡是InfluxData的官網,其open source的版本中有一個TICK stack的架構,包含了四個元件:


  • Telegraf:資料收集元件
  • InfluxDB:資料儲存元件
  • Chronograf:視覺化操作介面
  • Kapacitor:資料處理引擎
這四個元件組合起來,對大部分的應用來說,應該是相當充足了。

為熟悉InfluxDB,我們透過關聯式資料庫的概念來了解一下InfluxDB的架構。你也可以透過官網的Key concepts來做更深入的了解。
  • database:這個概念跟關聯式資料庫一樣
  • measurement:相當於表格(table)
  • tag:有索引的欄位 (indexed column)
  • field:沒有索引的欄位 (non-indexed column)
先提這四個名詞。如果各位想了解更多詞彙,可以參考官網上的Glossary

為了快速達到了解InfluxDB,我們只先專注在InfluxDB與Chronograf。首先先來安裝這兩個元件。我們以Windows為使用環境。請先到官網的下載頁面進行下載。

下載的是zip格式檔案,只要將之解壓縮即可。我們先來看influxdb.zip,解開後會有5個exe執行檔。主要的有兩個:influxd.exe是InfluxDB server,執行起來後可以看到這樣的畫面。server預設會使用port 8086來接收API指令。因此系統的安全設定上要允許使用這個port。資料庫預設的username及password都是root。

influx.exe 是client程式,我們可以利用這個程式來操作資料庫。直接執行後便可以連接到本機上資料庫。我們可以先試一個指令 "show databases" 來看看資料庫是否正常運作。如果有回應目前資料庫中databases清單,便表示系統正常運作。 (由於才剛剛安裝,應該只有 _internal 這個內部資料庫)
我們可以用exit指令來離開client程式。
InfluxDB使用的query language是InfluxQL,官網上有一頁做了與SQL的比較,大家可以參考一下。

接下來解開chronograf.zip後,有兩個exe。chronograf.exe是web server程式。執行後以瀏覽器連接 http://localhost:8888,就可以進入到視覺化界面。

我們可以先到configuration頁面檢視目前與InfluxDB server的連線狀況

到目前InfluxDB與Chronograf都完成安裝並可以正常執行。要停止這兩個server的執行,只要按ctrl-C即可。

下一篇,我們將寫個Python程式來為資料進資料庫,並在Chronograf中設定dashboard的圖表。

2019/01/14

時間序列資料與資料庫

再資料處理領域中,有一類型的資料是跟時間有密切關係的,這類的資料紀錄了某事物隨著時間變動的狀態,例如某商品的價格資訊、某廠房的環境溫溼度、某物流車的位置與速度等等。這些資料都屬於時間序列資料(Time-Series Data)。

這類型的資料有一些特質:

  • 資料是用時間排序的一組隨機變量,例如下圖,數值會隨著時間的變化而改變,因此時間是很重要的資料維度之一

  • 資料的產生可能是快速、大量且持續
    例如某個機台,每秒鐘會產生100筆資料,每筆資料約250KB,一天下來單單一個機台的資料量就高達2TB了,而且只要生產線保持運作,資料就不斷的產生
有相當多領域的資料都具有時間序列的特性,如計量經濟學、數學金融、天氣預報、地震預測、通信工程等等。尤其IoT物聯網應用蓬勃發展,時間序列資料的相關研究更會受到重視。

資料若要利用資訊系統來處理,儲存便是一個重要的課題。目前許多的應用中,會使用關聯式資料庫加上一個time-stamp欄位來解決這問題。若檢視時間序列資料的特質,我們要考量的因素有:

  • 資料是源源不斷產生,而且鮮少需要修改,因此insert的效能會是重要因素,update反而不那麼重要
  • 在一些應用中,資料的產生是快速且大量的,因此擴展性(scalability)就相當重要
  • 時間的運算常會是取回資料時常用到的功能,所以時間運算的效能很重要
對關聯式或其他資料庫來說,對上述的幾點的表現並沒有那麼亮眼,因此,有一時間序列資料庫(TSDB; Time-Series Database)這個分支,針對了時間序列資料的特質來量身打造了。目前市場上有相當多的TSDB系統,常見的可參考這篇wiki資料。目前較熱門的就以InfluxDB與Kdb+為主了。這一篇比較表也很有參考價值。

下一篇,我們將開始安裝與使用InfluxDB。

2018/10/17

Spring Boot 試作紀錄

工作上的系統,架構常用到micro-service,建立這些服務,常常都需要自己架構出需要的服務元件。常讀到Spring Boot的介紹,對它的自動化很好奇,趁著有個小空檔來試作一下。

試作目標:
  • 支援 static resources
  • 支援 servlets (HTTP request handler),收到request後,可根據client的資訊作回應
  • 嵌入Tomcat或Jetty

使用環境:Eclipse 2018-09

安裝 Spring Tools
進入Eclipse後,點選 Help | Eclipse Marketplace...
以 "spring tool" 就可找到 Spring Tools 4,點選Install即可安裝

建立 project
我們利用剛剛安裝的Spring Tools提供的工具來建立Spring Boot專案。
首先在主選單點選 File | New | Other...

選擇 Spring Boot | Spring Starter Project,然後進入Next

接下來要設定專案的相關資訊了,雖然事後都還可以調整,不過一開始就先設定好,後面可以省些事

幾個比較重要的欄位:
  • Name (專案名稱),這預設會連動到下面的Artifact ID
  • Type, Java Version, Language都使用預設,Packaging有Jar與War,看未來想打包成何種形式,可以在pom.xml中改變
  • Group (Group ID) 用來識別此專案的名稱 (可參考這裡),可以在pom.xml中改變
  • Artifact (Artiface ID)在未來產生Jar file時會用到這名稱,可以在pom.xml中改變
  • Version用來記錄版本,在未來產生Jar file時會用到,可以在pom.xml中改變
  • Description用來對這個專案作一個描述,可以在pom.xml中改變
  • Package則是建立程式時預設的package架構

接下來就要選擇專案需要的dependent libraries了,例如若專案需要用到PostgreSQL的JDBC driver,就可以直接勾選,Maven就會自動幫你下載了。
目前試作的專案只需要Web,所以就勾選Web即可。

點選Finish,Spring Tool就開始幫我們產生專案了。

Spring Tool幫我們產生了一個程式 GreetingApplication.java。這程式的內容很簡單,就只是啟動Spring Boot的應用


建立靜態網頁
靜態網頁與相關資源(js, css, etc.) 可以放在src/main/resources/static下。在此專案我們就放一個簡單的網頁。


page.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Welcome</title>
<link href="css/page.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Hello, welcome to static page.</h1>
</body>
</html>


page.css
h1 {
color: #ff7777;
font-style: italic;
}


建立Servlet (request handler)
接下來我們要進行動態回應的部分。我們列出需求:

  • 當使用者以POST或GET連結到 http://:8080/func時,則會由此handler來處理
  • 如果request parameter有name,我們就回覆 Hello, !,如果沒有name,則回覆 Hello, world!
  • 列出使用者的IP

我們建立的handler如下 (RequestHandler.java)
@RestController
public class RequestHandler {

    @RequestMapping(value="/func", method={RequestMethod.GET, RequestMethod.POST})
    public String handler1(@RequestParam(value="name", required=false) String name,
            HttpServletRequest request, HttpServletResponse response) {
        String user = (name==null || name.isEmpty())? "world": name;
        String host = request.getRemoteHost();
        String result = String.format("Hello, %s! You are from %s", user, host);
        return result;
    }
}


對此程式片段作一個註記:
  • @RestController:Spring採用MVC架構,註冊此程式為Controller
  • @RequestMapping:註冊此方法負責特定request的處理。value的值為URL對應的path,method則標記了要處理的方法
  • @RequestParam(value="name", required=false) String name
    Spring Boot會幫我們解析parameters,你可以將你需要的parameters都列出來。
    required預設為true,如果為false則表示此參數可能不存在於query string中
    解析出來的name值會放到字串name中
  • 因為我們需要使用者的IP,這需要從request物件中來取得,因此我們handler1的參數列加上了HttpServletRequest request,以便在程式中抓到IP
  • 雖然不會用到,我們也加上了HttpServletResponse response,若程式需要對response object作一些設定可以使用。在這個專案中是可以拿掉


執行
如果熟Eclipse的朋友就知道有很多種執行方法。這裡介紹其中一種,在project上按右鍵,Run As | Spring Boot App 就可以執行了


透過瀏覽器來看靜態網頁
以及動態內容


產生 JAR file
在project上按右鍵,Run As | Maven install就可以產生jar file了。

產生的jar file會放在專案的target目錄下。

所產生的jar file包含了專案所有需要的資源與libraries,因此只要把這個jar file放置到要執行程式的機器上,就可以執行這個服務了!
java -jar greeting-0.0.1.jar


由於這個jar file包含了必要的libraries,因此其file size大概都從15MB起跳。對大部分的運行環境應該都還能接受。

改內嵌 Jetty
Spring Boot 在 web應用上是預設內嵌Tomcat,若要改為使用Jetty,則需要修改pom.xml。現有的pom之片段是:

在這裡將Tomcat排除掉,再加入Jetty

這樣就可改用Jetty為平台了

修改port
這個系統預設是使用port 8080,若需要修改,可以直接在src/main/resources/application.properties中加上下列這行 (例如要改為port 88)
server.port = 88