Go 工作佇列範例

本範例會建立一個能顯示 HTML 表單的應用程式。您在對話方塊中輸入字串,然後按一下 Add。應用程式會計算您以這種方式輸入任何字串的次數。

應用程式會執行下列程序:

  • 當您按一下 Add 時,表單會使用 HTTP POST要求,將字串傳送至在 App Engine 上執行的應用程式。此時,應用程式會將字串與工作綁定成套件,再傳送至預設佇列 。
  • 佇列會將工作轉送至內含的工作處理常式,並對應至網址 /worker,後者會將字串非同步寫入資料儲存庫。
  • 傳送 HTTP GET 要求時,系統會顯示您輸入的字串清單,以及您Add 每個字串的次數 (輸入字串或在下拉式方塊中點選字串即可)。

將此應用程式部署至 App Engine:

  1. 將下列內容複製到名為 queue.yaml 的檔案中。這會將工作處理率從每秒 5 件的預設值變更為每秒 3 件。

    queue:
    - name: default
      rate: 3/s
    
  2. 在同一個目錄中,將下列內容複製到您想要的檔案中 (結尾為 .go)。這是應用程式程式碼,包括工作處理常式。

    
    package counter
    
    import (
    	"html/template"
    	"net/http"
    
    	"google.golang.org/appengine"
    	"google.golang.org/appengine/datastore"
    	"google.golang.org/appengine/log"
    	"google.golang.org/appengine/taskqueue"
    )
    
    func init() {
    	http.HandleFunc("/", handler)
    	http.HandleFunc("/worker", worker)
    }
    
    type Counter struct {
    	Name  string
    	Count int
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	ctx := appengine.NewContext(r)
    	if name := r.FormValue("name"); name != "" {
    		t := taskqueue.NewPOSTTask("/worker", map[string][]string{"name": {name}})
    		if _, err := taskqueue.Add(ctx, t, ""); err != nil {
    			http.Error(w, err.Error(), http.StatusInternalServerError)
    			return
    		}
    	}
    	q := datastore.NewQuery("Counter")
    	var counters []Counter
    	if _, err := q.GetAll(ctx, &counters); err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}
    	if err := handlerTemplate.Execute(w, counters); err != nil {
    		http.Error(w, err.Error(), http.StatusInternalServerError)
    		return
    	}
    	// OK
    }
    
    func worker(w http.ResponseWriter, r *http.Request) {
    	ctx := appengine.NewContext(r)
    	name := r.FormValue("name")
    	key := datastore.NewKey(ctx, "Counter", name, 0, nil)
    	var counter Counter
    	if err := datastore.Get(ctx, key, &counter); err == datastore.ErrNoSuchEntity {
    		counter.Name = name
    	} else if err != nil {
    		log.Errorf(ctx, "%v", err)
    		return
    	}
    	counter.Count++
    	if _, err := datastore.Put(ctx, key, &counter); err != nil {
    		log.Errorf(ctx, "%v", err)
    	}
    }
    
    var handlerTemplate = template.Must(template.New("handler").Parse(handlerHTML))
    
    const handlerHTML = `
    {{range .}}
    <p>{{.Name}}: {{.Count}}</p>
    {{end}}
    <p>Start a new counter:</p>
    <form action="/" method="POST">
    <input type="text" name="name">
    <input type="submit" value="Add">
    </form>
    `
    
  3. 在同一個目錄中,將以下內容複製到名為 app.yaml 的檔案中。隨即完成在 App Engine 中使用該應用程式的設定:

    runtime: go
    api_version: go1
    
    handlers:
    - url: /worker/.*
      script: _go_app
      login: admin
    - url: /.*
      script: _go_app
  4. 請確認您的 Google Cloud Platform 專案確實已備妥 App Engine 應用程式,您也已經初始化並設定該專案的 gcloud 指令。

  5. 使用 gcloud app deploy 指令將應用程式部署至 App Engine。

  6. 使用 gcloud app browse 指令查看應用程式執行情形。