Friday, February 24, 2017

tips on Golang Programing

tipsgolang

Tips for Go Programing

If you are working on No Network Environment, and you don't have a Golang book. How to keep working on when you forget how to use the command.

Go to the location you installed golang.

cd /usr/local/go/src

There are a lot of code on it.
Choose a command you want to know, select

grep select *

You will find a lot of example, and you might know how to write a correct code.
Of course, if you forget how to define function that how to return a channel. Try it.

grep chan *

You will find the answer.

Wednesday, February 15, 2017

golang http middleware ( net/http and httprouter+alice)

gomiddleware

Golang Middleware (net/http and httprouter+alice)

That's talk about Golang standard lib net/http and my favorate lib httprouter + alice.

Thanks for this blog, it really inspire me alot.

https://libraries.io/go/github.com%2Fmontanaflynn%2Fgo-middleware

Use Standard net/http

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func enableCORS(handler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
        if r.Method == "OPTIONS" {
            w.WriteHeader(200)
        }
        handler.ServeHTTP(w, r)
    })
}

func logRequests(handler http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        now := time.Now()
        method := r.Method
        path := r.URL.Path
        fmt.Printf("%v %s %s\n", now.Format("Jan 2, 2006 at 3:04pm (MST)"), method, path)
        handler.ServeHTTP(w, r)
    })
}

func delay(handler http.Handler, length string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        timeout, err := time.ParseDuration(length)
        if err != nil {
            log.Println("Could not parse delay length, skipping delay.")
            handler.ServeHTTP(w, r)
        }
        time.Sleep(timeout)
        handler.ServeHTTP(w, r)
    })
}
func helloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Println("haha in world ha")
    w.Write([]byte("Hello world!"))
}
func helloWorld1(str string) http.HandlerFunc {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("haha in world1 ha")
        w.Write([]byte("Hello world!"))
    })
}
func helloWorld2(str string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("haha in world2 ha")
        w.Write([]byte("Hello world!"))
    })
}
func main() {
    //app := delay(logRequests(enableCORS(http.HandlerFunc(helloWorld))), "1s")
    app := delay(logRequests(enableCORS(http.HandlerFunc(helloWorld1("5")))), "5s")
    //app := helloWorld2("5")
    http.ListenAndServe(":8080", app)

There are three types of calling helloWord(x) function.

  1. with middleware but without passing paramteters, said helloWorld

    app := delay(logRequests(enableCORS(http.HandlerFunc(helloWorld))), "1s")

  2. with middleware and with passing paramteters, said hellowWorld1

    app := delay(logRequests(enableCORS(http.HandlerFunc(helloWorld1("5")))), "5s")

  3. without middleware with parameter, said helloWorld2

    app := helloWorld2("5")

One can check the method related to its function call.

Httprouter and Alice

package main

import (
    "encoding/json"
    "fmt"
    "github.com/coreos/etcd/client"
    "github.com/gorilla/context"
    "github.com/julienschmidt/httprouter"
    "github.com/justinas/alice"
    "github.com/pborman/uuid"
    "io"
    "net/http"
    "os"
    "time"
)

func tokenHandler(next http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("into middle recover")

        // put process here
        token := r.Header.Get("Auth-Token")
        fmt.Println(token)
        if token == "powertoken" {
            next.ServeHTTP(w, r)
        }
        err := getTokenExist(kAPI, token)
        if err == nil {
            next.ServeHTTP(w, r)
        } else {

            http.Error(w, http.StatusText(401), 401)
        }
        // error oocured
    }
    return http.HandlerFunc(fn)
}

func wrapHandler(h http.Handler) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        context.Set(r, "params", ps)
        h.ServeHTTP(w, r)
    }
}
func getInfoHandler(w http.ResponseWriter, r *http.Request) {

    w.Header().Set("Content-Type", "application/json")
    //a := make(map[string]string)
    a := map[string]interface{}{}
    a["test"] = "haha"
    jsonString, _ := json.Marshal(a)
    //w.WriteHeader(200)
    w.Write(jsonString)
}

func getInfoHandler1(str string) http.HandlerFunc {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("I am here with str:", str)
        w.Header().Set("Content-Type", "application/json")
        //a := make(map[string]string)
        a := map[string]interface{}{}
        a["test"] = "haha"
        jsonString, _ := json.Marshal(a)
        //w.WriteHeader(200)
        w.Write(jsonString)
    })
}
func ttHandler(aa string) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        fmt.Println("in tt handler", aa)

        w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
        http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)

    }
}

func startWeb() {

    commonHandlers := alice.New(loggingHandler, tokenHandler, middlewareGenerator("foo", "foo2"))
    router := httprouter.New()
    router.GET("/version", wrapHandler(commonHandlers.ThenFunc(getInfoHandler)))
    router.GET("/version1", wrapHandler(commonHandlers.ThenFunc(getInfoHandler1("haha"))))

    aa := "strrrrr"
    router.GET("/tt", ttHandler(aa))
    http.ListenAndServe(":8080", router)
}

func main() {
    //println("start web")
    go startWeb()
    fmt.Println("start over")
    var input string
    fmt.Scanln(&input)
}

There are three points here.

  1. How to pass parameters to alice middleware said middlewareGenerator

    alice.New(loggingHandler, tokenHandler, middlewareGenerator("foo", "foo2"))

  2. How to pass parameters to httprouter and alice chain said getInfoHandler1

    router.GET("/version1", wrapHandler(commonHandlers.ThenFunc(getInfoHandler1("haha"))))

  3. How to pass parameters to httprouter said ttHandler

    router.GET("/tt", ttHandler(aa))

One can check the method related to its function call.

Conclustion

Now you have different way to deal with different situations.
Just copy and paste it.
Keep in mind, it's all about golang's wrap function and return value.

Tuesday, January 3, 2017

創業難

startup_diff

創業難

一直以來,我的偶像,翟神,其和沛公司竟也面臨縮編,這讓我感到非常的難受。
我,做雲端的技術已經超過五年了,過程,載浮載沉。
過去,也因為翟神幾個YouTube演說,讓我鼓起勇氣,脫離舒適圈,出來創業。
所以,創業的苦,當老闆的苦,我這兩年都經歷了。

因為當過老闆,所以我可以依照過去與翟神共事的經驗,更了解,翟神是個好老闆。
網路上有大量的批評對於翟神,但我必須說,對於關鍵人物,大家總是指指點點的。
這是關鍵人物的命運,將成為萬夫所指之人,所以,好壞都概夸承受吧,無所畏懼。
男子漢就是得撐起來,承受周圍的輿論,有冤妄才是有才的男子漢。
如果竭盡所能後,輿論與別人的想法,真的不必太在乎了。

當你能做到這樣,大部分那些批評你的人,真的差你很遠了。
或許,這樣的狀態,只能說明,
我們只能在,最壞的環境裡做到較好的結果。如此而已。

關鍵人物,起了關鍵作用,接下來,就是看周圍的人是否能夠將關鍵事情"撐"起來。
關鍵人物,技術產品,將技術或產品轉成財富,大家都知道,創業就這麼一回事。
和沛不乏超過三年以上雲端資歷的人,但,最終撐不起來?
誰的錯,翟神,和沛,金主,創投,台灣?

或者,這只是自然現象而已,不足懼。
鄉民拿著棒子的反應,只是呈現鄉民的思維罷了,不足取。
成與敗永遠都是自己引起的,這是關鍵人物必須有的態度。
但,
往往在過程中,不斷升級的是關鍵人物,而周圍的人,留在原地,跟不上。
有時候,關鍵人物需要的夥伴或許不需要最聰敏的,但也要腦袋夠活,手夠巧,腿夠勤才行。

這是一個很大的警訊,對於台灣的雲端產業,難道是最後一跟稻草?

Sunday, December 25, 2016

回顧2016

2016review

2016回顧

2016是一個很不容易的一年。 奔波在台灣與大陸間,有的時候,還覺得在大陸工作愉快些。
在這一年,學會了競爭與感激。 1. 競爭:
大陸團隊的擴張,我想做的只有一件事,當他們帶著挑戰的心情與我討論,我要讓他們笑的離開,並還會再找我討論。
2. 感激:
這一切都不容易,我感激我周遭的人,縱使他們因為無知而傷害著彼此,我感激他們。

多麼心機的一年,不舒服的一年,但也在此環境下成長,每一步,得學會忍耐與分析現狀,並突破自己。

在2016年開始時,我寫下了這一段話:

柔順謙遜,精中求細,剛健文明,應乎天時。

回頭看,這句話是完全正確的,我努力的奉行著,但卻不夠好。
很可惜,都知道答案了,卻無法100%的展現執行力,真的可惜。
各總情況的發生考驗著處理情緒的能力,忍靜著將一切轉成謀略。
我深知,必須忍耐著,不能忍,將無法執行任何謀略。
每一個狀況,我都在壓力下確認著,我到底要什麼,因此我該做什麼與不該做什麼。
每一個狀況,我都反覆思量著,我應該要用什麼態度,才能正確反應出我該有的反應。
聽起來就是很難受吧,是的,的確如此。
在我工作的周遭,不是朋友也沒有敵人,而這讓一切更不容易了。

常常,我把自己比喻成司馬懿,我還真他媽的處境有點類似。
在這樣的處境下生存著,那種懷疑與不信任對抗著,司馬懿不放棄,用了各種方法,而我也能撐過去。
撐,是一個很棒的字眼,有的時候撐過去,事情就會完全不同了。
這個司馬懿的比喻,讓我撐著渡過每個不愉悅,甘心忍耐與等待,並讓每個謀略實現。
在那時,我寫下這段話:

享受競爭。
享受人與人之間的懷疑不信任。
享受內與外的不協調。
享受忍耐與低調。
享受恐懼與不確定。
我已經不能停下腳步了。
因為那種不舒服的感覺只是感覺罷了。
沒什麼了不起。
因為世界很大.所以沒什麼好怕的。
要突破就享受這一切吧。
但,其實反著說,
臉皮厚,心要黑,才能享受這ㄧ切。

很悲傷,真的,我是如此悲傷的寫下這段話。
這違反著我這幾年工作的方法,態度,經驗,我不喜歡。
但我得這麼去做,這麼去想,唯有這樣,事情會更順利些。 因為,我了解,最重要的是,事情能夠做好。
透過這樣的修正,慢慢的我也懂得如何思考,如何放置那些讓人不愉悅的人,並讓自己得利,讓事情順利:

有一個正面的模仿對象,可以讓你方向正確,同時有一個負面的討厭對象,可以讓你更積極的邁開步伐走向正確方向。

所有的目的,是讓事情完成,而事情是人做的,但人很複雜。
必須用以大事小的態度對待你的周圍。
運行正確的態度,包含: 不亂抱怨,沒有過多的情緒,學習讓爭論互有勝負。

  1. 不亂抱怨:
    在一個會議裡,如果只是抱怨著講師的內容, 這,不代表你比他懂,反而,最終,你毫無所得。 這個現象,屢試不爽。有時候,我們得想想,為何而來.....。 是要學點東西回去,還是來此否定一切。

    贏家專注在自己的跑道,酸民看著別人的跑道。

  2. 沒有過多的情緒:
    過去,曾經有個同事,完全無法控制自己的情緒(我們都犯過這樣的錯)。 在辦公室中多次咆嘯,我看懂了這種醜陋與噁心,因此努力的阻止自己變成這樣的人。
    當發現用情緒做事的人是如此可悲與幼稚,誰也不願意成為那樣的人吧。

    用謀略完成事情,而不是情緒,情緒只會將事情搞砸。要控制情緒,先閉起你的嘴吧。

  3. 在同一個團體中,讓爭論互有勝負
    爭論,是一件複雜的事情,你想贏是吧! 如果只是爭著贏,而不讓別人在這過程中,也獲得一些小勝利,這不是贏。
    讓別人贏一些,只要當最大的贏家即可,不用全贏。
    多讚美人,讓人感覺自己是中立的,讓步,是因為展現中立,得到別人的信賴。
    因此,最後,你的堅持,會讓別人更認同你。所以,在不重要的地方讓步,在重要的地方堅持。

    總是在立場上爭到頭破血流是件蠢事,笑到最後的才是贏家,看著自己的謀略一步一步被實踐才叫成功。

在2016,一切都不容易,內憂外患,要克服這些,只能不斷的修煉自己。
但縱使如此,我感激這些人,事,物。

反思這一年,自己依舊不夠勤勞,沒有投入100%的時間,讓事情更偉大。

Think Big, Doing Big, Win Big.

所以,用馬雲的一句話送給2017年的自己吧

感激過去,珍惜現在,敬畏明天

Tuesday, November 8, 2016

Influxdb Installation and Playing

influxdb

InfluxDB Testing

Installation

Get influxdb apt repository

wget -O- https://repos.influxdata.com/influxdb.key | apt-key add -
root@influxdb:~# apt-key list
/etc/apt/trusted.gpg
--------------------
.
.

pub   4096R/2582E0C5 2015-09-28
uid                  InfluxDB Packaging Service <support@influxdb.com>
sub   4096R/87F70D56 2015-09-28
root@influxdb:~# source /etc/lsb-release
root@influxdb:~# echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | tee /etc/apt/sources.list.d/influxdb.list

Update Repository and install influxdb

root@influxdb1:~#apt-get update
root@influxdb1:~# apt-get -y install influxdb
.
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  influxdb
0 upgraded, 1 newly installed, 0 to remove and 174 not upgraded.
Need to get 17.8 MB of archives.
After this operation, 64.0 MB of additional disk space will be used.
Fetched 17.8 MB in 57s (308 kB/s)
Selecting previously unselected package influxdb.
(Reading database ... 49929 files and directories currently installed.)
Preparing to unpack .../influxdb_1.0.2-1_amd64.deb ...
Unpacking influxdb (1.0.2-1) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Setting up influxdb (1.0.2-1) ...
 Adding system startup for /etc/init.d/influxdb ...
   /etc/rc0.d/K20influxdb -> ../init.d/influxdb
   /etc/rc1.d/K20influxdb -> ../init.d/influxdb
   /etc/rc6.d/K20influxdb -> ../init.d/influxdb
   /etc/rc2.d/S20influxdb -> ../init.d/influxdb
   /etc/rc3.d/S20influxdb -> ../init.d/influxdb
   /etc/rc4.d/S20influxdb -> ../init.d/influxdb
   /etc/rc5.d/S20influxdb -> ../init.d/influxdb

Start playing

Use 8086 port.

Create DB first

root@influxdb1:~# curl -X POST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
{"results":[{}]}

Write data

root@influxdb1:~# curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server02 value=0.67'
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: bef013e7-a593-11e6-8004-000000000000
X-Influxdb-Version: 1.0.2
Date: Tue, 08 Nov 2016 09:14:26 GMT

Query data

root@influxdb1:~# curl -i 'http://localhost:8086/query?db=mydb' --data-urlencode "q=SELECT value FROM cpu_load_short"
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Request-Id: 0707f706-a594-11e6-8007-000000000000
X-Influxdb-Version: 1.0.2
Date: Tue, 08 Nov 2016 09:16:27 GMT
Transfer-Encoding: chunked

{"results":[{"series":[{"name":"cpu_load_short","columns":["time","value"],"values":[["2016-11-08T09:14:26.355967704Z",0.67]]}]}]}

Monday, November 7, 2016

Numa Setting

numa

Numa Setting

What is a Numa

Simplly said, Numa has a share memory charachtoristic.
Numa node means share the same pool of memory.
So if a process running in same Numa node, it will get better performance.
Let's see it.

Check Server Numa Node

To get Numa node

[root@openstackha11 ~]# cat /sys/devices/system/node/
has_cpu            node0/             possible
has_memory         node1/             power/
has_normal_memory  online             uevent

To get Numa node's CPU

[root@openstackha11 ~]# cat /sys/devices/system/node/node0/cpulist
0-5,12-17
[root@openstackha11 ~]# cat /sys/devices/system/node/node1/cpulist
6-11,18-23

Set Numa for a Process

Set up a Process to a CPU range(Numa Node)

[root@openstackha11 ~]# taskset -cp 6-11,18-23 24122
pid 24122's current affinity list: 0-23
pid 24122's new affinity list: 6-11,18-23
You have new mail in /var/spool/mail/root

where 6-11,18-23 obtained by numa node.

Tuesday, November 1, 2016

公司食物鏈

公司的食物鏈,依序是
搞關係,搞錢,搞人,搞很多很多事,搞很多事,只搞一件事。

你是哪一項?而你的目標又在哪?