めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

Implementing a counter service with Bigtable

Cloud Datastore is the best friend for App Engine developers, yeay!

However, it may be awkward to implement an incremental counter (like AUTO_INCREMENT in MySQL) over Datastore. The good alternative is to use Bigtable to implement a counter service.

Here is a prototype of such a counter service. getCount() returns an auto increment integer number starting from 1 with strong consistency. In this sample, five of go-routines keep getting counts until they receive 100 counts per routine which results in 500 counts in total.

Before running this on Cloud Shell, you need to create a Bigtable cluster and install golang client SDK with the following command.

$ go get -u all

main.go

package main
import (
        "flag"
        "encoding/binary"
        "log"
        "sync"
        "cloud.google.com/go/bigtable"
        "golang.org/x/net/context"
)
// User-provided constants.
const (
        tableName        = "CounterTable"
        columnFamilyName = "count"
        columnName       = ""
        rowName          = "mycounter"
)

// sliceContains reports whether the provided string is present in the given slice of strings.
func sliceContains(list []string, target string) bool {
        for _, s := range list {
                if s == target {
                        return true
                }
        }
        return false
}

func main() {
        project := flag.String("project", "", "The Google Cloud Platform project ID. Required.")
        instance := flag.String("instance", "", "The Google Cloud Bigtable instance ID. Required.")
        flag.Parse()

        for _, f := range []string{"project", "instance"} {
                if flag.Lookup(f).Value.String() == "" {
                        log.Fatalf("The %s flag is required.", f)
                }
        }

        ctx := context.Background()
        adminClient, err := bigtable.NewAdminClient(ctx, *project, *instance)
        if err != nil {
                log.Fatalf("Could not create admin client: %v", err)
        }

        tables, err := adminClient.Tables(ctx)
        if err != nil {
                log.Fatalf("Could not fetch table list: %v", err)
        }

        if !sliceContains(tables, tableName) {
                log.Printf("Creating table %s", tableName)
                if err := adminClient.CreateTable(ctx, tableName); err != nil {
                        log.Fatalf("Could not create table %s: %v", tableName, err)
                }
        }

        tblInfo, err := adminClient.TableInfo(ctx, tableName)
        if err != nil {
                log.Fatalf("Could not read info for table %s: %v", tableName, err)
        }

        if !sliceContains(tblInfo.Families, columnFamilyName) {
                if err := adminClient.CreateColumnFamily(ctx, tableName, columnFamilyName); err != nil {
                        log.Fatalf("Could not create column family %s: %v", columnFamilyName, err)
                }
        }

        client, err := bigtable.NewClient(ctx, *project, *instance)
        if err != nil {
                log.Fatalf("Could not create data operations client: %v", err)
        }

        tbl := client.Open(tableName)
        mut := bigtable.NewMutation()
        mut.Set(columnFamilyName, columnName, bigtable.Now(),[]byte{0, 0, 0, 0, 0, 0, 0, 0}) 

        if err := tbl.Apply(ctx, rowName, mut); err != nil {
                log.Fatalf("Could not create row: %v", err)
        }

        // counter service function
        getCount := func() uint64 {
                rmw := bigtable.NewReadModifyWrite()
                rmw.Increment(columnFamilyName, columnName, 1)
                row, err := tbl.ApplyReadModifyWrite(ctx, rowName, rmw)
                if err != nil {
                         log.Fatalf("Could not update row: %s %v", row, err)
                }
                data := binary.BigEndian.Uint64(row[columnFamilyName][0].Value)
                return data
        }

        var wg sync.WaitGroup
        for i := 0; i < 5; i++ {
                wg.Add(1)
                go func(id int) {
                        log.Printf("Start client:%d", id)
                        for j := 1; j < 101; j++ {
                                data := getCount()
                                log.Printf("\tclient:%d\t%s = %d\n", id, rowName, data)
                        }
                        log.Printf("Finished client:%d", id)
                        wg.Done()
                }(i)
        }
        wg.Wait()
        log.Printf("Finished.")
}
$ go run main.go -project bt-counter -instance mycounter
2016/11/11 10:55:54 Start client:4
2016/11/11 10:55:54 Start client:0
2016/11/11 10:55:54 Start client:1
2016/11/11 10:55:54 Start client:2
2016/11/11 10:55:54 Start client:3
2016/11/11 10:55:54     client:2        mycounter = 1
2016/11/11 10:55:54     client:1        mycounter = 2
2016/11/11 10:55:54     client:2        mycounter = 3
2016/11/11 10:55:54     client:0        mycounter = 4
2016/11/11 10:55:54     client:1        mycounter = 5
2016/11/11 10:55:54     client:2        mycounter = 6
2016/11/11 10:55:54     client:3        mycounter = 7
2016/11/11 10:55:54     client:0        mycounter = 8
2016/11/11 10:55:54     client:4        mycounter = 9
2016/11/11 10:55:54     client:2        mycounter = 10
2016/11/11 10:55:54     client:1        mycounter = 11
2016/11/11 10:55:54     client:3        mycounter = 12
2016/11/11 10:55:54     client:4        mycounter = 14
2016/11/11 10:55:54     client:2        mycounter = 15
2016/11/11 10:55:54     client:1        mycounter = 16
2016/11/11 10:55:54     client:4        mycounter = 17
2016/11/11 10:55:54     client:2        mycounter = 18
2016/11/11 10:55:54     client:1        mycounter = 19
2016/11/11 10:55:54     client:2        mycounter = 20
2016/11/11 10:55:54     client:1        mycounter = 21
2016/11/11 10:55:54     client:2        mycounter = 22
2016/11/11 10:55:54     client:0        mycounter = 13
2016/11/11 10:55:54     client:2        mycounter = 23
2016/11/11 10:55:54     client:1        mycounter = 24
2016/11/11 10:55:54     client:4        mycounter = 25
2016/11/11 10:55:54     client:3        mycounter = 26
2016/11/11 10:55:54     client:0        mycounter = 27
2016/11/11 10:55:54     client:2        mycounter = 28
2016/11/11 10:55:54     client:1        mycounter = 29
2016/11/11 10:55:54     client:4        mycounter = 30
2016/11/11 10:55:54     client:3        mycounter = 31
2016/11/11 10:55:54     client:0        mycounter = 32
2016/11/11 10:55:54     client:2        mycounter = 33
2016/11/11 10:55:54     client:1        mycounter = 34
2016/11/11 10:55:54     client:4        mycounter = 35
2016/11/11 10:55:54     client:3        mycounter = 36
2016/11/11 10:55:54     client:2        mycounter = 38
2016/11/11 10:55:54     client:0        mycounter = 37
2016/11/11 10:55:54     client:1        mycounter = 39
2016/11/11 10:55:54     client:4        mycounter = 40
2016/11/11 10:55:54     client:3        mycounter = 41
2016/11/11 10:55:54     client:2        mycounter = 42
2016/11/11 10:55:54     client:0        mycounter = 43
2016/11/11 10:55:54     client:1        mycounter = 44
2016/11/11 10:55:54     client:4        mycounter = 45
2016/11/11 10:55:54     client:3        mycounter = 46
2016/11/11 10:55:54     client:2        mycounter = 47
2016/11/11 10:55:54     client:1        mycounter = 49
2016/11/11 10:55:54     client:4        mycounter = 50
2016/11/11 10:55:54     client:0        mycounter = 48
2016/11/11 10:55:54     client:2        mycounter = 52
2016/11/11 10:55:54     client:1        mycounter = 53
2016/11/11 10:55:54     client:4        mycounter = 54
2016/11/11 10:55:54     client:0        mycounter = 55
2016/11/11 10:55:54     client:3        mycounter = 51
2016/11/11 10:55:54     client:2        mycounter = 56
2016/11/11 10:55:54     client:1        mycounter = 57
2016/11/11 10:55:54     client:4        mycounter = 58
2016/11/11 10:55:54     client:0        mycounter = 59
2016/11/11 10:55:54     client:3        mycounter = 60
2016/11/11 10:55:54     client:2        mycounter = 61
2016/11/11 10:55:54     client:1        mycounter = 62
2016/11/11 10:55:54     client:4        mycounter = 63
2016/11/11 10:55:54     client:0        mycounter = 64
2016/11/11 10:55:54     client:3        mycounter = 65
2016/11/11 10:55:54     client:2        mycounter = 66
2016/11/11 10:55:54     client:1        mycounter = 67
2016/11/11 10:55:54     client:4        mycounter = 68
2016/11/11 10:55:54     client:3        mycounter = 70
2016/11/11 10:55:55     client:4        mycounter = 73
2016/11/11 10:55:55     client:1        mycounter = 72
2016/11/11 10:55:55     client:2        mycounter = 71
2016/11/11 10:55:55     client:0        mycounter = 69
2016/11/11 10:55:55     client:3        mycounter = 74
2016/11/11 10:55:55     client:4        mycounter = 75
2016/11/11 10:55:55     client:1        mycounter = 76
2016/11/11 10:55:55     client:2        mycounter = 77
2016/11/11 10:55:55     client:0        mycounter = 78
2016/11/11 10:55:55     client:3        mycounter = 79
2016/11/11 10:55:55     client:4        mycounter = 80
2016/11/11 10:55:55     client:2        mycounter = 82
2016/11/11 10:55:55     client:1        mycounter = 81
2016/11/11 10:55:55     client:0        mycounter = 83
2016/11/11 10:55:55     client:3        mycounter = 84
2016/11/11 10:55:55     client:4        mycounter = 85
2016/11/11 10:55:55     client:2        mycounter = 86
2016/11/11 10:55:55     client:1        mycounter = 87
2016/11/11 10:55:55     client:0        mycounter = 88
2016/11/11 10:55:55     client:3        mycounter = 89
2016/11/11 10:55:55     client:4        mycounter = 90
2016/11/11 10:55:55     client:2        mycounter = 91
2016/11/11 10:55:55     client:1        mycounter = 92
2016/11/11 10:55:55     client:4        mycounter = 94
2016/11/11 10:55:55     client:0        mycounter = 93
2016/11/11 10:55:55     client:3        mycounter = 95
2016/11/11 10:55:55     client:2        mycounter = 96
2016/11/11 10:55:55     client:1        mycounter = 97
2016/11/11 10:55:55     client:0        mycounter = 98
2016/11/11 10:55:55     client:4        mycounter = 99
2016/11/11 10:55:55     client:3        mycounter = 100
2016/11/11 10:55:55     client:2        mycounter = 101
2016/11/11 10:55:55     client:1        mycounter = 102
2016/11/11 10:55:55     client:0        mycounter = 103
2016/11/11 10:55:55     client:4        mycounter = 104
2016/11/11 10:55:55     client:3        mycounter = 105
2016/11/11 10:55:55     client:2        mycounter = 106
2016/11/11 10:55:55     client:1        mycounter = 107
2016/11/11 10:55:55     client:0        mycounter = 108
2016/11/11 10:55:55     client:4        mycounter = 109
2016/11/11 10:55:55     client:3        mycounter = 110
2016/11/11 10:55:55     client:2        mycounter = 111
2016/11/11 10:55:55     client:1        mycounter = 112
2016/11/11 10:55:55     client:0        mycounter = 113
2016/11/11 10:55:55     client:4        mycounter = 114
2016/11/11 10:55:55     client:3        mycounter = 115
2016/11/11 10:55:55     client:2        mycounter = 116
2016/11/11 10:55:55     client:0        mycounter = 118
2016/11/11 10:55:55     client:4        mycounter = 119
2016/11/11 10:55:55     client:3        mycounter = 120
2016/11/11 10:55:55     client:2        mycounter = 121
2016/11/11 10:55:55     client:1        mycounter = 117
2016/11/11 10:55:55     client:0        mycounter = 122
2016/11/11 10:55:55     client:4        mycounter = 123
2016/11/11 10:55:55     client:3        mycounter = 124
2016/11/11 10:55:55     client:2        mycounter = 125
2016/11/11 10:55:55     client:1        mycounter = 126
2016/11/11 10:55:55     client:0        mycounter = 127
2016/11/11 10:55:55     client:4        mycounter = 128
2016/11/11 10:55:55     client:3        mycounter = 129
2016/11/11 10:55:55     client:2        mycounter = 130
2016/11/11 10:55:55     client:1        mycounter = 131
2016/11/11 10:55:55     client:0        mycounter = 132
2016/11/11 10:55:55     client:4        mycounter = 133
2016/11/11 10:55:55     client:3        mycounter = 134
2016/11/11 10:55:55     client:2        mycounter = 135
2016/11/11 10:55:55     client:1        mycounter = 136
2016/11/11 10:55:55     client:0        mycounter = 137
2016/11/11 10:55:55     client:4        mycounter = 138
2016/11/11 10:55:55     client:3        mycounter = 139
2016/11/11 10:55:55     client:1        mycounter = 140
2016/11/11 10:55:55     client:2        mycounter = 141
2016/11/11 10:55:55     client:0        mycounter = 142
2016/11/11 10:55:55     client:4        mycounter = 143
2016/11/11 10:55:55     client:3        mycounter = 144
2016/11/11 10:55:55     client:1        mycounter = 145
2016/11/11 10:55:55     client:2        mycounter = 146
2016/11/11 10:55:55     client:0        mycounter = 147
2016/11/11 10:55:55     client:4        mycounter = 148
2016/11/11 10:55:55     client:3        mycounter = 149
2016/11/11 10:55:55     client:1        mycounter = 150
2016/11/11 10:55:55     client:2        mycounter = 151
2016/11/11 10:55:55     client:4        mycounter = 152
2016/11/11 10:55:55     client:0        mycounter = 153
2016/11/11 10:55:55     client:3        mycounter = 154
2016/11/11 10:55:55     client:1        mycounter = 155
2016/11/11 10:55:55     client:2        mycounter = 156
2016/11/11 10:55:55     client:4        mycounter = 157
2016/11/11 10:55:55     client:0        mycounter = 158
2016/11/11 10:55:55     client:3        mycounter = 159
2016/11/11 10:55:55     client:1        mycounter = 160
2016/11/11 10:55:55     client:2        mycounter = 161
2016/11/11 10:55:55     client:4        mycounter = 162
2016/11/11 10:55:55     client:0        mycounter = 163
2016/11/11 10:55:55     client:3        mycounter = 164
2016/11/11 10:55:55     client:1        mycounter = 165
2016/11/11 10:55:55     client:2        mycounter = 166
2016/11/11 10:55:55     client:4        mycounter = 167
2016/11/11 10:55:55     client:0        mycounter = 168
2016/11/11 10:55:55     client:3        mycounter = 169
2016/11/11 10:55:55     client:2        mycounter = 171
2016/11/11 10:55:55     client:4        mycounter = 172
2016/11/11 10:55:55     client:0        mycounter = 173
2016/11/11 10:55:55     client:1        mycounter = 170
2016/11/11 10:55:55     client:3        mycounter = 174
2016/11/11 10:55:55     client:2        mycounter = 175
2016/11/11 10:55:55     client:4        mycounter = 176
2016/11/11 10:55:55     client:0        mycounter = 177
2016/11/11 10:55:55     client:1        mycounter = 178
2016/11/11 10:55:55     client:3        mycounter = 179
2016/11/11 10:55:55     client:2        mycounter = 180
2016/11/11 10:55:55     client:4        mycounter = 181
2016/11/11 10:55:55     client:0        mycounter = 182
2016/11/11 10:55:55     client:1        mycounter = 183
2016/11/11 10:55:55     client:3        mycounter = 184
2016/11/11 10:55:55     client:2        mycounter = 185
2016/11/11 10:55:55     client:4        mycounter = 186
2016/11/11 10:55:55     client:0        mycounter = 187
2016/11/11 10:55:55     client:1        mycounter = 188
2016/11/11 10:55:55     client:3        mycounter = 189
2016/11/11 10:55:55     client:2        mycounter = 190
2016/11/11 10:55:55     client:4        mycounter = 191
2016/11/11 10:55:55     client:0        mycounter = 192
2016/11/11 10:55:55     client:1        mycounter = 193
2016/11/11 10:55:55     client:3        mycounter = 194
2016/11/11 10:55:55     client:2        mycounter = 195
2016/11/11 10:55:55     client:4        mycounter = 196
2016/11/11 10:55:55     client:0        mycounter = 197
2016/11/11 10:55:55     client:1        mycounter = 198
2016/11/11 10:55:55     client:3        mycounter = 199
2016/11/11 10:55:55     client:2        mycounter = 200
2016/11/11 10:55:55     client:4        mycounter = 201
2016/11/11 10:55:55     client:0        mycounter = 202
2016/11/11 10:55:55     client:1        mycounter = 203
2016/11/11 10:55:55     client:3        mycounter = 204
2016/11/11 10:55:55     client:2        mycounter = 205
2016/11/11 10:55:55     client:4        mycounter = 206
2016/11/11 10:55:55     client:0        mycounter = 207
2016/11/11 10:55:55     client:1        mycounter = 208
2016/11/11 10:55:55     client:3        mycounter = 209
2016/11/11 10:55:55     client:2        mycounter = 210
2016/11/11 10:55:55     client:4        mycounter = 211
2016/11/11 10:55:55     client:0        mycounter = 212
2016/11/11 10:55:55     client:1        mycounter = 213
2016/11/11 10:55:55     client:3        mycounter = 214
2016/11/11 10:55:55     client:2        mycounter = 215
2016/11/11 10:55:55     client:4        mycounter = 216
2016/11/11 10:55:55     client:0        mycounter = 217
2016/11/11 10:55:55     client:1        mycounter = 218
2016/11/11 10:55:55     client:3        mycounter = 219
2016/11/11 10:55:55     client:2        mycounter = 220
2016/11/11 10:55:55     client:4        mycounter = 221
2016/11/11 10:55:55     client:0        mycounter = 222
2016/11/11 10:55:55     client:1        mycounter = 223
2016/11/11 10:55:55     client:3        mycounter = 224
2016/11/11 10:55:55     client:2        mycounter = 225
2016/11/11 10:55:55     client:0        mycounter = 227
2016/11/11 10:55:55     client:1        mycounter = 228
2016/11/11 10:55:55     client:4        mycounter = 226
2016/11/11 10:55:55     client:2        mycounter = 230
2016/11/11 10:55:55     client:3        mycounter = 229
2016/11/11 10:55:55     client:0        mycounter = 231
2016/11/11 10:55:55     client:1        mycounter = 232
2016/11/11 10:55:55     client:4        mycounter = 233
2016/11/11 10:55:55     client:2        mycounter = 234
2016/11/11 10:55:55     client:3        mycounter = 235
2016/11/11 10:55:55     client:0        mycounter = 236
2016/11/11 10:55:55     client:1        mycounter = 237
2016/11/11 10:55:55     client:4        mycounter = 238
2016/11/11 10:55:55     client:2        mycounter = 239
2016/11/11 10:55:55     client:3        mycounter = 240
2016/11/11 10:55:55     client:0        mycounter = 241
2016/11/11 10:55:55     client:1        mycounter = 242
2016/11/11 10:55:55     client:4        mycounter = 243
2016/11/11 10:55:55     client:2        mycounter = 244
2016/11/11 10:55:55     client:3        mycounter = 245
2016/11/11 10:55:55     client:0        mycounter = 246
2016/11/11 10:55:55     client:1        mycounter = 247
2016/11/11 10:55:55     client:4        mycounter = 248
2016/11/11 10:55:55     client:3        mycounter = 250
2016/11/11 10:55:55     client:2        mycounter = 249
2016/11/11 10:55:55     client:0        mycounter = 251
2016/11/11 10:55:55     client:1        mycounter = 252
2016/11/11 10:55:55     client:4        mycounter = 253
2016/11/11 10:55:55     client:3        mycounter = 254
2016/11/11 10:55:55     client:2        mycounter = 255
2016/11/11 10:55:55     client:0        mycounter = 256
2016/11/11 10:55:55     client:1        mycounter = 257
2016/11/11 10:55:55     client:4        mycounter = 258
2016/11/11 10:55:55     client:3        mycounter = 259
2016/11/11 10:55:55     client:2        mycounter = 260
2016/11/11 10:55:55     client:0        mycounter = 261
2016/11/11 10:55:55     client:1        mycounter = 262
2016/11/11 10:55:55     client:4        mycounter = 263
2016/11/11 10:55:55     client:3        mycounter = 264
2016/11/11 10:55:55     client:2        mycounter = 265
2016/11/11 10:55:55     client:0        mycounter = 266
2016/11/11 10:55:55     client:1        mycounter = 267
2016/11/11 10:55:55     client:4        mycounter = 268
2016/11/11 10:55:55     client:3        mycounter = 269
2016/11/11 10:55:55     client:2        mycounter = 270
2016/11/11 10:55:55     client:0        mycounter = 271
2016/11/11 10:55:55     client:1        mycounter = 272
2016/11/11 10:55:55     client:4        mycounter = 273
2016/11/11 10:55:55     client:3        mycounter = 274
2016/11/11 10:55:55     client:2        mycounter = 275
2016/11/11 10:55:55     client:0        mycounter = 276
2016/11/11 10:55:55     client:1        mycounter = 277
2016/11/11 10:55:55     client:4        mycounter = 278
2016/11/11 10:55:55     client:3        mycounter = 279
2016/11/11 10:55:55     client:2        mycounter = 280
2016/11/11 10:55:55     client:0        mycounter = 281
2016/11/11 10:55:55     client:1        mycounter = 282
2016/11/11 10:55:55     client:4        mycounter = 283
2016/11/11 10:55:55     client:3        mycounter = 284
2016/11/11 10:55:55     client:2        mycounter = 285
2016/11/11 10:55:55     client:0        mycounter = 286
2016/11/11 10:55:55     client:1        mycounter = 287
2016/11/11 10:55:55     client:4        mycounter = 288
2016/11/11 10:55:55     client:0        mycounter = 290
2016/11/11 10:55:55     client:3        mycounter = 289
2016/11/11 10:55:55     client:2        mycounter = 291
2016/11/11 10:55:55     client:1        mycounter = 292
2016/11/11 10:55:55     client:4        mycounter = 293
2016/11/11 10:55:55     client:0        mycounter = 294
2016/11/11 10:55:55     client:3        mycounter = 295
2016/11/11 10:55:55     client:2        mycounter = 296
2016/11/11 10:55:55     client:1        mycounter = 297
2016/11/11 10:55:55     client:4        mycounter = 298
2016/11/11 10:55:55     client:0        mycounter = 299
2016/11/11 10:55:55     client:3        mycounter = 300
2016/11/11 10:55:55     client:2        mycounter = 301
2016/11/11 10:55:55     client:1        mycounter = 302
2016/11/11 10:55:55     client:4        mycounter = 303
2016/11/11 10:55:55     client:0        mycounter = 304
2016/11/11 10:55:55     client:3        mycounter = 305
2016/11/11 10:55:55     client:2        mycounter = 306
2016/11/11 10:55:55     client:1        mycounter = 307
2016/11/11 10:55:55     client:4        mycounter = 308
2016/11/11 10:55:55     client:0        mycounter = 309
2016/11/11 10:55:55     client:3        mycounter = 310
2016/11/11 10:55:55     client:2        mycounter = 311
2016/11/11 10:55:55     client:1        mycounter = 312
2016/11/11 10:55:55     client:4        mycounter = 313
2016/11/11 10:55:55     client:3        mycounter = 315
2016/11/11 10:55:55     client:0        mycounter = 314
2016/11/11 10:55:55     client:2        mycounter = 316
2016/11/11 10:55:55     client:1        mycounter = 317
2016/11/11 10:55:55     client:3        mycounter = 318
2016/11/11 10:55:55     client:4        mycounter = 319
2016/11/11 10:55:55     client:0        mycounter = 320
2016/11/11 10:55:55     client:1        mycounter = 322
2016/11/11 10:55:55     client:2        mycounter = 321
2016/11/11 10:55:55     client:3        mycounter = 323
2016/11/11 10:55:55     client:4        mycounter = 324
2016/11/11 10:55:55     client:0        mycounter = 325
2016/11/11 10:55:55     client:1        mycounter = 326
2016/11/11 10:55:55     client:2        mycounter = 327
2016/11/11 10:55:55     client:3        mycounter = 328
2016/11/11 10:55:55     client:1        mycounter = 330
2016/11/11 10:55:55     client:4        mycounter = 329
2016/11/11 10:55:55     client:0        mycounter = 331
2016/11/11 10:55:55     client:2        mycounter = 332
2016/11/11 10:55:55     client:3        mycounter = 333
2016/11/11 10:55:55     client:1        mycounter = 334
2016/11/11 10:55:55     client:4        mycounter = 335
2016/11/11 10:55:55     client:0        mycounter = 336
2016/11/11 10:55:55     client:2        mycounter = 337
2016/11/11 10:55:55     client:3        mycounter = 338
2016/11/11 10:55:55     client:1        mycounter = 339
2016/11/11 10:55:55     client:4        mycounter = 340
2016/11/11 10:55:55     client:0        mycounter = 341
2016/11/11 10:55:55     client:2        mycounter = 342
2016/11/11 10:55:55     client:3        mycounter = 343
2016/11/11 10:55:55     client:4        mycounter = 345
2016/11/11 10:55:55     client:0        mycounter = 346
2016/11/11 10:55:55     client:2        mycounter = 347
2016/11/11 10:55:55     client:1        mycounter = 344
2016/11/11 10:55:55     client:3        mycounter = 348
2016/11/11 10:55:55     client:4        mycounter = 349
2016/11/11 10:55:55     client:0        mycounter = 350
2016/11/11 10:55:55     client:2        mycounter = 351
2016/11/11 10:55:55     client:1        mycounter = 352
2016/11/11 10:55:55     client:4        mycounter = 354
2016/11/11 10:55:55     client:3        mycounter = 353
2016/11/11 10:55:55     client:0        mycounter = 355
2016/11/11 10:55:55     client:2        mycounter = 356
2016/11/11 10:55:55     client:1        mycounter = 357
2016/11/11 10:55:55     client:4        mycounter = 358
2016/11/11 10:55:55     client:3        mycounter = 359
2016/11/11 10:55:55     client:0        mycounter = 360
2016/11/11 10:55:55     client:2        mycounter = 361
2016/11/11 10:55:55     client:1        mycounter = 362
2016/11/11 10:55:55     client:4        mycounter = 363
2016/11/11 10:55:55     client:3        mycounter = 364
2016/11/11 10:55:55     client:2        mycounter = 366
2016/11/11 10:55:55     client:1        mycounter = 367
2016/11/11 10:55:55     client:0        mycounter = 365
2016/11/11 10:55:55     client:4        mycounter = 368
2016/11/11 10:55:55     client:3        mycounter = 369
2016/11/11 10:55:55     client:1        mycounter = 371
2016/11/11 10:55:55     client:2        mycounter = 370
2016/11/11 10:55:55     client:0        mycounter = 372
2016/11/11 10:55:55     client:4        mycounter = 373
2016/11/11 10:55:55     client:3        mycounter = 374
2016/11/11 10:55:55     client:1        mycounter = 375
2016/11/11 10:55:55     client:2        mycounter = 376
2016/11/11 10:55:55     client:0        mycounter = 377
2016/11/11 10:55:55     client:4        mycounter = 378
2016/11/11 10:55:55     client:3        mycounter = 379
2016/11/11 10:55:55     client:1        mycounter = 380
2016/11/11 10:55:55     client:2        mycounter = 381
2016/11/11 10:55:55     client:0        mycounter = 382
2016/11/11 10:55:55     client:4        mycounter = 383
2016/11/11 10:55:55     client:3        mycounter = 384
2016/11/11 10:55:55     client:2        mycounter = 386
2016/11/11 10:55:55     client:1        mycounter = 385
2016/11/11 10:55:55     client:0        mycounter = 387
2016/11/11 10:55:55     client:4        mycounter = 388
2016/11/11 10:55:55     client:3        mycounter = 389
2016/11/11 10:55:55     client:2        mycounter = 390
2016/11/11 10:55:55     client:1        mycounter = 391
2016/11/11 10:55:55     client:0        mycounter = 392
2016/11/11 10:55:55     client:4        mycounter = 393
2016/11/11 10:55:55     client:3        mycounter = 394
2016/11/11 10:55:55     client:2        mycounter = 395
2016/11/11 10:55:55     client:1        mycounter = 396
2016/11/11 10:55:55     client:4        mycounter = 398
2016/11/11 10:55:55     client:0        mycounter = 397
2016/11/11 10:55:55     client:3        mycounter = 399
2016/11/11 10:55:55     client:2        mycounter = 400
2016/11/11 10:55:55     client:4        mycounter = 402
2016/11/11 10:55:55     client:1        mycounter = 401
2016/11/11 10:55:55     client:0        mycounter = 403
2016/11/11 10:55:55     client:3        mycounter = 404
2016/11/11 10:55:55     client:4        mycounter = 405
2016/11/11 10:55:55     client:2        mycounter = 406
2016/11/11 10:55:55     client:1        mycounter = 407
2016/11/11 10:55:55     client:0        mycounter = 408
2016/11/11 10:55:55     client:3        mycounter = 409
2016/11/11 10:55:55     client:4        mycounter = 410
2016/11/11 10:55:55     client:2        mycounter = 411
2016/11/11 10:55:55     client:1        mycounter = 412
2016/11/11 10:55:55     client:3        mycounter = 414
2016/11/11 10:55:55     client:0        mycounter = 413
2016/11/11 10:55:55     client:4        mycounter = 415
2016/11/11 10:55:55     client:2        mycounter = 416
2016/11/11 10:55:55     client:3        mycounter = 418
2016/11/11 10:55:55     client:1        mycounter = 417
2016/11/11 10:55:55     client:0        mycounter = 419
2016/11/11 10:55:55     client:4        mycounter = 420
2016/11/11 10:55:55     client:2        mycounter = 421
2016/11/11 10:55:55     client:3        mycounter = 422
2016/11/11 10:55:55     client:1        mycounter = 423
2016/11/11 10:55:55     client:0        mycounter = 424
2016/11/11 10:55:55     client:2        mycounter = 426
2016/11/11 10:55:55     client:4        mycounter = 425
2016/11/11 10:55:55     client:3        mycounter = 427
2016/11/11 10:55:55     client:1        mycounter = 428
2016/11/11 10:55:55     client:0        mycounter = 429
2016/11/11 10:55:55     client:2        mycounter = 430
2016/11/11 10:55:55     client:4        mycounter = 431
2016/11/11 10:55:55     client:3        mycounter = 432
2016/11/11 10:55:55     client:0        mycounter = 433
2016/11/11 10:55:55     client:2        mycounter = 435
2016/11/11 10:55:55     client:1        mycounter = 434
2016/11/11 10:55:55     client:4        mycounter = 436
2016/11/11 10:55:55     client:3        mycounter = 437
2016/11/11 10:55:55     client:0        mycounter = 438
2016/11/11 10:55:55     client:2        mycounter = 439
2016/11/11 10:55:55     client:1        mycounter = 440
2016/11/11 10:55:55     client:3        mycounter = 442
2016/11/11 10:55:55     client:0        mycounter = 443
2016/11/11 10:55:55     client:4        mycounter = 441
2016/11/11 10:55:55     client:2        mycounter = 444
2016/11/11 10:55:55     client:0        mycounter = 446
2016/11/11 10:55:55     client:1        mycounter = 445
2016/11/11 10:55:55     client:3        mycounter = 447
2016/11/11 10:55:55     client:4        mycounter = 448
2016/11/11 10:55:55     client:2        mycounter = 449
2016/11/11 10:55:55     client:1        mycounter = 450
2016/11/11 10:55:55     client:0        mycounter = 451
2016/11/11 10:55:55     client:3        mycounter = 452
2016/11/11 10:55:55     client:1        mycounter = 454
2016/11/11 10:55:55     client:4        mycounter = 453
2016/11/11 10:55:55     client:2        mycounter = 455
2016/11/11 10:55:55     client:0        mycounter = 456
2016/11/11 10:55:55     client:1        mycounter = 458
2016/11/11 10:55:55     client:3        mycounter = 457
2016/11/11 10:55:55     client:4        mycounter = 459
2016/11/11 10:55:55     client:2        mycounter = 460
2016/11/11 10:55:55     client:0        mycounter = 461
2016/11/11 10:55:55     client:3        mycounter = 463
2016/11/11 10:55:55     client:1        mycounter = 462
2016/11/11 10:55:55     client:4        mycounter = 464
2016/11/11 10:55:55     client:2        mycounter = 465
2016/11/11 10:55:55     client:0        mycounter = 466
2016/11/11 10:55:55     client:3        mycounter = 467
2016/11/11 10:55:55     client:1        mycounter = 468
2016/11/11 10:55:55     client:2        mycounter = 469
2016/11/11 10:55:55     client:4        mycounter = 470
2016/11/11 10:55:55     client:0        mycounter = 471
2016/11/11 10:55:55     client:3        mycounter = 472
2016/11/11 10:55:55     client:2        mycounter = 473
2016/11/11 10:55:55 Finished client:2
2016/11/11 10:55:55     client:1        mycounter = 474
2016/11/11 10:55:55     client:4        mycounter = 475
2016/11/11 10:55:55     client:0        mycounter = 476
2016/11/11 10:55:55     client:3        mycounter = 477
2016/11/11 10:55:55     client:4        mycounter = 478
2016/11/11 10:55:55     client:1        mycounter = 479
2016/11/11 10:55:55     client:0        mycounter = 480
2016/11/11 10:55:55     client:4        mycounter = 481
2016/11/11 10:55:55     client:3        mycounter = 482
2016/11/11 10:55:55     client:1        mycounter = 483
2016/11/11 10:55:55     client:0        mycounter = 484
2016/11/11 10:55:55     client:4        mycounter = 485
2016/11/11 10:55:55     client:3        mycounter = 486
2016/11/11 10:55:55     client:1        mycounter = 487
2016/11/11 10:55:55     client:0        mycounter = 488
2016/11/11 10:55:55     client:1        mycounter = 491
2016/11/11 10:55:55 Finished client:1
2016/11/11 10:55:55     client:3        mycounter = 490
2016/11/11 10:55:55     client:4        mycounter = 489
2016/11/11 10:55:55     client:0        mycounter = 492
2016/11/11 10:55:55     client:3        mycounter = 493
2016/11/11 10:55:55     client:4        mycounter = 494
2016/11/11 10:55:55 Finished client:4
2016/11/11 10:55:55     client:0        mycounter = 495
2016/11/11 10:55:55     client:3        mycounter = 496
2016/11/11 10:55:55     client:0        mycounter = 497
2016/11/11 10:55:55     client:3        mycounter = 498
2016/11/11 10:55:55     client:0        mycounter = 499
2016/11/11 10:55:55 Finished client:0
2016/11/11 10:55:55     client:3        mycounter = 500
2016/11/11 10:55:55 Finished client:3
2016/11/11 10:55:55 Finished.

It works! Now you can create an API service for providing counters running on App Engine. You may need to use a flexible environment since go client library is not supported on the standard environment at the time of writing.

Disclaimer: All code snippets are released under Apache 2.0 License. This is not an official Google product.