自從有了 Let’s Encrypt 以後,網站的 ssl 憑證都是用他們家
免費的憑証,原本的設定都是把 nginx 擺在前面,利用 virtual host
的方式,可以對應到多個站點,用 acme.sh
command line 的工具去管理,多個站點的 ssl 憑証更新,時間久了,還是
覺得麻煩,後來乾脆,直接只跑一個 golang 的 server 同時 host 多個站點
自從有了 Let’s Encrypt 以後,網站的 ssl 憑證都是用他們家
免費的憑証,原本的設定都是把 nginx 擺在前面,利用 virtual host
的方式,可以對應到多個站點,用 acme.sh
command line 的工具去管理,多個站點的 ssl 憑証更新,時間久了,還是
覺得麻煩,後來乾脆,直接只跑一個 golang 的 server 同時 host 多個站點
最近有個面試的回家作業,做了一個簡單的爬蟲
單純只有爬一下,家樂福,還有大潤發的網站,一家是用 HTML 不斷的翻頁下去,爬完休息
另一家,直接找他的 json api ,直接抓 api 的結果就可以了
目前整個 code base 挑出來的毛病,或是說,用一個微小的專案,來看軟體開發這件事,需要具備的東西
也是一個不錯的自我成長方式,可以一步一步看,目前用 golang 來實作一些,像是後端服務的一些處理模式
會寫出來,主要是也許會對剛好有機會碰到,這些問題的人有幫助
code reference https://github.com/terryh/honestman
我先列一些一般來說用 golang 來寫一些像是 api 服務的問題,或是比較像是軟體的架構模式來討論
1) crawler (爬蟲) 的 go routine 模式
2) 要用 ORM 來抽象化 SQL 的操作好,還是不用 ORM 來操作
3) 你需要用 framework 嗎?
4) simple test case and benchmark ?
由於,這其實是一個可大可小的題目,但是,我還是來簡單說一下,目前,一般用 golang 做 web service ,或是給手遊用的
後端服務介面,或是手機應用程式的 api 介面,大概會用哪一些函式庫
如果,開發團隊人員不多,對整個 http/s 或是網路服務認識不多,會選,既有的框架
目前,比較受歡迎的有
https://github.com/gin-gonic/gin
https://github.com/astaxie/beego
https://github.com/labstack/echo
我個人比較推薦是相容於 golang http library http.HandlerFunc 的 framework
如果不要框架,選擇更多,但是,這種人必須比較專業,也要更了解要處理的問題,還有 golang standard library ,因為,要有能力可以判斷,
像大家建議的 COMPOSITION 方式 https://www.youtube.com/watch?v=194blNHDdd0
自己組建比較多,就是選用一個 http router dispacher
這個則是有很多的參考,或是選擇 https://github.com/julienschmidt/go-http-routing-benchmark
剩下的大概就是組建自己的服務了
需要 HTML, JSON render 的,或是需要驗證身份,或是希望引用 ORM 來達到和 DB 層的抽象化,這些每一種都一個選擇,伴
隨著也都是取捨的問題
未完待續,接下來,上面列出的點,會做作小筆記,也希望對需要的人有幫助 ;-)
先前後端開發 web service 大多是以小型的 web framework echo 來做基礎開發
https://github.com/labstack/echo
到了後來,因為他新版 v2 api 的介面修改,包了另一個 http engine fasthttp 的模組,雖然多了一層的彈性
多了一個選擇,但是在 golang 1.7 版以後,標準的函式庫已經包含了 context ,所有 framework 要解決的問題
幾乎都可以用標準函式庫,就全可以解決了,也可以真正體會 composition 組件式的架構方式,第三方的函式也更容易整併
請務必試試看,用 golang 標準的函式庫,加上一些第三方的函式,組建 web service
更新待續
在網路上,有很多 Docker 的佈署的文章,或是用來測試的方式
用 golang 撰寫的服務,編譯成執行檔後,你可以有很多的選擇,例如:upstart , supervisord , 或是 daemontools
這一次,我想用 Docker ,想要他的彈性
但是,不管用 Ubuntu , Debian 或是官方的 Golang 的 image
總覺得 image 太大,不合用,直接由 scratch 做 image 又覺得,萬一有一些系統的相依套件,需要的時候,不方便
所以這是我目前的萬用 image 的 Dockerfile
FROM alpine:3.2
RUN apk –update add curl
WORKDIR /usr/src/app
ENTRYPOINT ["/usr/src/app/goapp"]
覺得簡單易懂的好文章
可以讓你用 golang 寫 api 有一個簡單的開始
http://nicolasmerouze.com/guide-routers-golang/
另外也推薦他的 gist ,再把 main 的部份,拔出來,做一個 NewRouter 應該更好測試,再加幾個函式庫,就是一個 micro framework 了
作者這一系列的文章 http://nicolasmerouze.com/build-web-framework-golang/
相關也推再看 alice 模組作者的文章,雖然 alice 很單純,單純到自己刻,可能也只有 5 行左右
不過看一下,作者的實作概念,挺不錯的
https://justinas.org/alice-painless-middleware-chaining-for-go/
https://github.com/justinas/alice
https://github.com/julienschmidt/httprouter
https://github.com/gorilla/context
首先您必須到 https://developer.apple.com/ 去新增一個 App,一般就是你要用 push notification 的應用程式
設定好名字,還有 ID ,記得要把 Push Notifications 的服務打勾
我這裡說明就用中文,因為英文的說明有一堆了
接下來就可以打開您的 Mac / 應用程式 / 工具程式 / 鑰匙圈存取
我們選憑證輔助程式,從憑證授權要求憑證
把他存下來,我舉的例子就叫 PushMsg ,把檔名改成 PushMsg 所以你會得到 PushMsg.certSigningRequest 這一個 CSR ,待會要到 apple 網站上面產生憑證
產生後,到鑰匙圈存取 應用程式,選鑰匙的地方,你會看到有 PushMsg 的公鑰和密鑰,點選專用密鑰,按下滑鼠右鍵輸出憑證,輸出成 PushMsg.p12 待會用
這時候,請用剛剛的 PushMsg.certSigningRequest 到 Apple 開發者網站的 App 設定 notification 的地方去產生憑證,可以下載後,
開發模式,你會得到 aps_development.cer ,實際部署模式,請依此類推
我們現在有 PushMsg.certSigningRequest , PushMsg.p12 , 還有 aps_development.cer 接下來,我們來產生,Server 端程式需要的憑證格式
這裡的程式,我們用 Golang 的範例,其他用 Python , Node.js 或是其他語言的朋友請依此類推
產生 cert.pem
openssl x509 -in aps_development.cer -inform der -out cert.pem
openssl pkcs12 -in PushMsg.p12 -out key.pem -nodes
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert cert.pem -key key.pem
package main
import (
“crypto/tls”
“fmt”
“net”
“os”
)
func main() {
// load
cert, err := tls.LoadX509KeyPair("./cert.pem", “./key.pem”)
if err != nil {
fmt.Println(“key error: “, err)
os.Exit(1)
}
conf := &tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: “gateway.sandbox.push.apple.com”,
}
// connect to APPLE
conn, err := net.Dial(“tcp”, “gateway.sandbox.push.apple.com:2195”)
if err != nil {
fmt.Println(“tcp error: “, err)
os.Exit(1)
}
tlsconn := tls.Client(conn, conf)
// be nice
err = tlsconn.Handshake()
if err != nil {
fmt.Println(“tls error: “, err)
os.Exit(1)
}
}
這一個 golang 裡面非常帥氣的 library ,作者是原 memcached 的作者之一,主要就是讓 cache 機制再簡化
集群的部署能力也還不錯,完全不用再管 server instance ,我對這種,以簡單為名的 library 最沒有招架能力了
https://github.com/golang/groupcache
使用上也是非常的帥氣,可以參考 OSCON 的簡報
http://talks.golang.org/2013/oscon-dl.slide#1
詳細的使用上可以參考, source code ,或是 test case,還有很多種用法
以下是我用的範例,您可以用在很多地方,像是外部 url fetch ,或是很重的 query 或是檔案 IO 之類的
就是平常,你 cache 怎麼用,就可以怎麼用,cache 只有支援 拿,和寫,
以下的例子用這樣拿資料,我的 cache key 大概到小時,就用自己算每小時不同的 key
FileInfoCache.Get(nil, cacheFileInfo, groupcache.AllocatingByteSliceSink(&data))
另外,FileInfoFetch 就是另外一個做很多 disk IO 的工作
dest.SetBytes(FileInfoFetch(path))
// Example for groupcache
// snip from my code
var (
FileInfoCache *groupcache.Group
)
func init(){
//////////////////////////////////////////
// init book query cache
//cacheAddr := “127.0.0.1:55555”
//peers := groupcache.NewHTTPPool(“http://” + cacheAddr)
// the cache key is compose with timestamp hour
// 2006-01-02 15!!!url
getter := groupcache.GetterFunc(func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
keys := strings.SplitN(key, “!!!”, 2)
//ts := keys[0]
path := keys[1]
dest.SetBytes(FileInfoFetch(path))
return nil
})
if FileInfoCache == nil {
// cache not been init
// allocate 64 MB memory for groupcache
FileInfoCache = groupcache.NewGroup(“FileInfo”, 64«20, getter)
}
}