Tutorial: Menggunakan Memorystore for Redis sebagai papan peringkat game


Tutorial ini menunjukkan kepada Anda cara menggunakan Memorystore for Redis untuk membangun aplikasi papan peringkat berbasis ASP.NET yang berjalan di Google Kubernetes Engine (GKE), kemudian memposting dan mendapatkan skor menggunakan contoh game terpisah berbasis JavaScript. Dokumen ini ditujukan bagi developer game yang ingin mengoperasikan papan peringkat mereka sendiri di cloud.

Pengantar

Papan peringkat adalah fitur umum dalam game multiplayer. Papan peringkat menampilkan peringkat pemain secara real time, yang membantu mendorong pemain untuk lebih aktif dalam bermain game. Untuk menangkap tindakan pemain dan menentukan peringkat skor secara real time, database dalam memori seperti Redis adalah pilihan yang tepat.

Diagram berikut menunjukkan infrastruktur papan peringkat:

Diagram yang menunjukkan cluster GKE
di dalam VPC, dan instance Memorystore for Redis terpisah.

Di Google Cloud, papan peringkat terdiri dari cluster GKE di dalam jaringan VPC, dan instance Memorystore for Redis terpisah.

Diagram berikut menampilkan arsitektur aplikasi untuk tutorial ini. Klien menggunakan API papan peringkat untuk berinteraksi dengan skor yang dipertahankan dalam instance Memorystore for Redis yang berjalan di Google Cloud.

Diagram yang menampilkan arsitektur untuk aplikasi dalam tutorial ini

Metode API papan peringkat

API untuk aplikasi papan peringkat menyertakan metode berikut:

  • PostScore(string playerName, double score). Metode ini memposting skor ke papan peringkat untuk pemain yang ditentukan.
  • RetrieveScores(string centerKey, int offset, int numScores). Metode ini mendownload serangkaian skor. Jika Anda meneruskan ID pemain sebagai nilai untuk centerKey, metode ini akan menampilkan skor yang berada di atas dan di bawah skor dari pemain yang ditentukan. Jika Anda tidak meneruskan nilai untuk centerKey, metode akan menampilkan skor N absolut teratas, dengan N adalah nilai yang Anda teruskan di numScores. Misalnya, untuk mendapatkan 10 skor teratas, panggil RetrieveScores('', 0, 10). Untuk mendapatkan 5 skor di atas dan di bawah skor pemain, panggil RetrieveScores('player1', -5, 10).

Repositori kode untuk contoh tersebut mencakup game tiruan dan implementasi papan peringkat bukti konsep. Selama tutorial ini, Anda akan men-deploy game dan papan peringkat, serta memvalidasi bahwa API papan peringkat berfungsi dengan benar dan dapat diakses melalui internet.

Tujuan

  • Membuat instance Memorystore for Redis.
  • Membuat layanan headless dengan endpoint yang mengarahkan permintaan ke instance ini.
  • Men-deploy aplikasi papan peringkat ke GKE.
  • Memverifikasi fungsi papan peringkat menggunakan aplikasi yang di-deploy dan melakukan panggilan API.

Biaya

Dalam dokumen ini, Anda menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga. Pengguna baru Google Cloud mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Sebelum memulai

  1. Login ke akun Google Cloud Anda. Jika Anda baru menggunakan Google Cloud, buat akun untuk mengevaluasi performa produk kami dalam skenario dunia nyata. Pelanggan baru juga mendapatkan kredit gratis senilai $300 untuk menjalankan, menguji, dan men-deploy workload.
  2. Di konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.

    Buka pemilih project

  3. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  4. Enable the Memorystore for Redis and Google Kubernetes Engine APIs.

    Enable the APIs

  5. Di konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.

    Buka pemilih project

  6. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  7. Enable the Memorystore for Redis and Google Kubernetes Engine APIs.

    Enable the APIs

Mempersiapkan lingkungan Anda

Dalam tutorial ini, Anda akan menjalankan perintah di Cloud Shell. Cloud Shell memberi Anda akses ke command line di Google Cloud, dan mencakup Google Cloud CLI serta alat lain yang Anda perlukan untuk pengembangan Google Cloud. Cloud Shell dapat memerlukan waktu beberapa menit untuk proses inisialisasi.

  1. Buka Cloud Shell:

    Buka Cloud Shell

  2. Setel zona Compute Engine default ke zona tempat Anda akan membuat resource Google Cloud. Dalam tutorial ini, Anda menggunakan zona us-central1-a di region us-central1.

    export REGION=us-central1
    export ZONE=us-central1-a
    gcloud config set compute/zone $ZONE
    
  3. Clone repositori GitHub yang berisi kode contoh:

    git clone https://github.com/GoogleCloudPlatform/memstore-gaming-leaderboard.git
    
  4. Buka direktori yang telah di-clone:

    cd memstore-gaming-leaderboard
    
  5. Dengan menggunakan editor teks, buka file leaderboardapp/k8s/appdeploy.yaml dan ubah placeholder [YOUR_PROJECT_ID] ke ID project Google Cloud Anda.

Membuat instance Memorystore for Redis

Pada tutorial ini, Anda akan membuat instance Paket Dasar Memorystore for Redis, yang sesuai untuk pengujian dan cakupan tutorial ini. Untuk deployment produksi, sebaiknya deploy instance Tingkat Standar, yang memberikan SLA 99,9% dengan failover otomatis untuk memastikan bahwa instance Anda sangat tersedia. Untuk mengetahui detail tentang instance Tingkat Standar, lihat ketersediaan tinggi untuk Memorystore for Redis.

  • Di Cloud Shell, buat instance Memorystore for Redis sebesar 1 GB:

    gcloud redis instances create cm-redis --size=1 \
      --tier=basic \
      --region=$REGION \
      --zone=$ZONE
    

    Pemrosesan perintah ini mungkin membutuhkan waktu beberapa menit.

Mem-build image container aplikasi

Pada tutorial ini, Anda akan men-deploy aplikasi papan peringkat sederhana menggunakan GKE. Karena Unity dan C# populer dalam game, tingkat aplikasi menggunakan C# dan framework ASP.NET.

Untuk men-deploy API papan peringkat ke cluster GKE, Anda harus menguploadnya terlebih dahulu ke registry seperti Container Registry.

  1. Buka file README.md di project GitHub yang Anda clone.
  2. Ikuti petunjuk untuk membuat image Docker dan menguploadnya ke Container Registry.

Anda akan menggunakan image ini untuk men-deploy aplikasi papan peringkat setelah membuat cluster di bagian berikutnya.

Membuat atau menggunakan kembali cluster GKE

Sebelum men-deploy aplikasi papan peringkat, Anda harus membuat cluster GKE dengan rentang IP alias yang diaktifkan. Jika sudah memiliki cluster GKE (menggunakan rentang IP alias), Anda dapat menggunakan cluster tersebut untuk tutorial ini. Jika menggunakan cluster yang ada, Anda harus melakukan langkah tambahan untuk mengonfigurasi alat command line kubectl dengan kredensial untuk cluster tersebut.

  1. Jika Anda ingin membuat cluster, buat cluster bernama leaderboard yang memiliki dua node:

    gcloud container clusters create leaderboard --num-nodes=2 --enable-ip-alias
    

    Pemrosesan perintah ini membutuhkan waktu beberapa menit.

  2. Setelah menunggu cluster untuk memulai, pastikan cluster sudah berjalan:

    gcloud container clusters list
    

    Cluster sedang berjalan saat Anda melihat entri dengan nama leaderboard yang statusnya adalah RUNNING.

Mengonfigurasi kredensial untuk cluster yang ada

  1. Jika Anda menggunakan cluster GKE yang sudah ada untuk tutorial ini, konfigurasikan file kubeconfig dengan kredensial untuk cluster tersebut. Untuk name-of-existing-cluster, gunakan nama cluster Anda.

    gcloud container clusters get-credentials name-of-existing-cluster
    

Memetakan instance Memorystore for Redis ke layanan Kubernetes

Ketika instance Memorystore for Redis siap, buat layanan di dalam cluster GKE agar tingkat aplikasi dapat terhubung.

  1. Pastikan instance Memorystore for Redis berjalan:

    gcloud redis instances list --region=$REGION
    

    Anda akan melihat output seperti berikut:

    INSTANCE_NAME  VERSION    REGION           TIER       SIZE_GB    HOST       PORT  NETWORK  RESERVED_IP  STATUS    CREATE_TIME
    cm-redis       REDIS_4_0  us-central1      STANDARD  1            10.0.0.3  6379  default  10.0.0.0/29  READY     2019-05-10T04:37:45
    

    Instance berjalan saat kolom STATUS menampilkan READY. Instance belum menyelesaikan proses startup jika kolom HOST kosong. Tunggu sebentar lalu jalankan kembali perintah redis instances list.

  2. Simpan alamat IP instance dalam variabel lingkungan:

    export REDIS_IP=$(gcloud redis instances list --filter="name:cm-redis" --format="value(HOST)" \
        --region=$REGION)
    
  3. Membuat layanan Kubernetes untuk Redis:

    kubectl apply -f k8s/redis_headless_service.yaml
    

    Layanan ini tidak memiliki pemilih Pod, karena Anda menginginkannya untuk menunjuk ke alamat IP yang berada di luar cluster Kubernetes.

  4. Buat endpoint yang menentukan alamat IP Redis yang Anda ambil sebelumnya:

    sed "s|REDIS_IP|${REDIS_IP}|g" k8s/redis_endpoint.yaml | kubectl apply -f -
    
  5. Pastikan layanan dan endpoint telah dibuat dengan benar:

    kubectl get services/redis endpoints/redis
    

    Jika semuanya berfungsi dengan benar, Anda akan melihat output seperti berikut, dengan entri untuk layanan Redis dan endpoint Redis:

    NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    service/redis      ClusterIP   10.59.241.103   none        6379/TCP   5m
    
    NAME               ENDPOINTS       AGE
    endpoints/redis    10.0.0.3:6379   4m
    

Untuk mengetahui informasi selengkapnya tentang layanan dan endpoint Kubernetes, lihat Praktik terbaik Kubernetes: memetakan layanan eksternal di blog Google Cloud.

Men-deploy aplikasi papan peringkat dan layanan ke Kubernetes

Instance Redis sekarang dapat dijangkau dari aplikasi yang di-deploy di cluster GKE. Karenanya, Anda siap men-deploy aplikasi papan peringkat.

  • Ikuti petunjuk dalam file README.md yang disertakan dalam root repositori GitHub yang Anda clone sebelumnya.

Memvalidasi deployment

Aplikasi game tiruan yang disediakan, yang ditulis dalam JavaScript, dapat digunakan untuk melakukan panggilan ke API papan peringkat. Cuplikan kode berikut menunjukkan cara game tiruan memposting skor setelah pemain selesai bermain:

                    var scoreInfo = {
                        playerName: this.username,
                        score: this.calculateScore().toFixed(2)
                    };

                    var pThis = this;

                    var postUrl = "/api/score";
                    (async () => {
                        try {
                            await axios.post(postUrl, scoreInfo)
                        } catch (error) {
                            console.error(error);
                        }

                        var lbPromise = pThis.fetchLeaderboard();
                        var qPromise = pThis.fetchQuestions();

                        pThis.questions = await qPromise;
                        await lbPromise;
                    })();

Selain itu, aplikasi akan melakukan panggilan API untuk mengambil skor papan peringkat—skor teratas atau skor yang berpusat di sekitar nama pemain, seperti ini:

                    var pThis = this;
                    var getUrl = "/api/score/retrievescores";

                    (async () => {
                        try {
                            var params = {
                                centerKey: '',
                                offset: 0,
                                numScores: 11
                            };

                            if (pThis.centered) {
                                params.centerKey = pThis.username;
                                params.offset = -5;
                                params.numScores = 11;
                            }

                            const response = await axios.get(getUrl, { params: params });
                            pThis.leaderboard = response.data;
                        } catch (error) {
                            console.error(error);
                            return []
                        }
                    })();

Untuk mengakses aplikasi contoh, ikuti langkah-langkah berikut:

  1. Dapatkan alamat IP game tiruan dengan menjalankan perintah berikut:

    kubectl get ingress
    

    Outputnya mirip dengan hal berikut ini:

    NAME                      HOSTS   ADDRESS        PORTS   AGE
    memstore-gaming-ingress   *       34.102.192.4   80      43s
    
  2. Buka URL berikut, dengan ip_address_for_gke sebagai alamat game tiruan:

    http://ip_address_for_gke.
    

Contoh ini sederhana, tetapi memadai untuk menunjukkan penggunaan API dasar. Saat Anda memposting atau mengambil skor langsung dari aplikasi klien game yang berjalan di perangkat pengguna atau komputer, contoh game memanggil API papan peringkat di alamat IP publik yang ditetapkan ke objek Load Balancer Kubernetes-nya. Untuk aplikasi contoh ini, API papan peringkat dan klien JavaScript dihosting di alamat IP yang sama dengan yang Anda dapatkan dengan menggunakan perintah kubectl get ingress yang ditampilkan sebelumnya.

Bagaimana metode tersebut diimplementasikan

Aplikasi papan peringkat, yang ditulis dalam C#, menggunakan library StackExchange.Redis untuk berkomunikasi dengan Redis. Cuplikan kode berikut menunjukkan cara PostScore dan RetrieveScores diimplementasikan menggunakan Redis dan library StackExchange.Redis.

Cuplikan kode berikut menunjukkan metode PostScore:

        public async Task<bool> PostScoreAsync(ScoreModel score)
        {
            IDatabase db = _redis.GetDatabase();

            // SortedSetAddAsync corresponds to ZADD
            return await db.SortedSetAddAsync(LEADERBOARD_KEY, score.PlayerName, score.Score);
        }

Cuplikan kode berikut menunjukkan metode RetrieveScores:

        public async Task<IList<LeaderboardItemModel>> RetrieveScoresAsync(RetrieveScoresDetails retrievalDetails)
        {
            IDatabase db = _redis.GetDatabase();
            List<LeaderboardItemModel> leaderboard = new List<LeaderboardItemModel>();

            long offset = retrievalDetails.Offset;
            long numScores = retrievalDetails.NumScores;

            // If centered, get rank of specified user first
            if (!string.IsNullOrWhiteSpace(retrievalDetails.CenterKey))
            {
                // SortedSetRankAsync corresponds to ZREVRANK
                var rank = await db.SortedSetRankAsync(LEADERBOARD_KEY, retrievalDetails.CenterKey, Order.Descending);

                // If specified user is not present, return empty leaderboard
                if (!rank.HasValue)
                {
                    return leaderboard;
                }

                // Use rank to calculate offset
                offset = Math.Max(0, rank.Value + retrievalDetails.Offset);

                // Account for number of scores when we're attempting to center
                // at element in rank [0, abs(offset))
                if(offset <= 0)
                {
                    numScores = rank.Value + Math.Abs((long)retrievalDetails.Offset) + 1;
                }
            }

            // SortedSetRangeByScoreWithScoresAsync corresponds to ZREVRANGEBYSCORE [WITHSCORES]
            var scores = await db.SortedSetRangeByScoreWithScoresAsync(LEADERBOARD_KEY,
                skip: offset,
                take: numScores,
                order: Order.Descending);

            var startingRank = offset;
            for (int i = 0; i < scores.Length; i++)
            {
                var lbItem = new LeaderboardItemModel
                {
                    Rank = startingRank++,
                    PlayerName = scores[i].Element.ToString(),
                    Score = scores[i].Score
                };
                leaderboard.Add(lbItem);
            }

            return leaderboard;
        }

Penambahan ke contoh game

API papan peringkat mengikuti konvensi REST dan hanya disediakan sebagai contoh. Saat Anda menjalankan papan peringkat game produksi, sebaiknya integrasikan alur autentikasi sehingga hanya skor yang berasal dari pengguna yang telah divalidasi yang dapat diposting.

Saat ini, Memorystore for Redis tidak menyediakan persistensi untuk skor pemain. Oleh karena itu, jika aplikasi mengalami masalah, Anda dapat kehilangan informasi papan peringkat. Jika game Anda memerlukan papan peringkat persisten, Anda harus mencadangkan skor papan peringkat secara berkala dalam database yang persisten.

Pembersihan

Hapus project untuk menghindari biaya pada akun Google Cloud pada resource yang digunakan dalam tutorial ini.

Menghapus project

  1. Di konsol Google Cloud, buka halaman Manage resource.

    Buka Manage resource

  2. Pada daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.

Langkah selanjutnya