Blog AWS Indonesia

Visualisasi Big Data dengan AWS AppSync, Amazon Athena dan AWS Amplify

Organisasi menggunakan big data dan analitik untuk memperoleh informasi yang dapat ditindaklanjuti dari kumpulan data yang belum dimanfaatkan. Anda kemungkinan juga akan sulit untuk membangun aplikasi dengan akses ke kumpulan data ini. Anda ingin membangun aplikasi hebat dengan cepat dan membutuhkan akses ke peralatan yang memungkinkan Anda berinteraksi dengan data secara mudah.

Mempresentasikan data juga memiliki tantangan yang sama. Tabel berisi angka dan kata kunci mungkin gagal menyampaikan pesan yang dimaksudkan dan mempersulit penyampaian hasil pengamatan yang mendalam. Bagan data, grafik, dan gambar lebih baik dalam menyampaikan ide dan pola yang kompleks.

Tulisan ini menunjukkan cara menggunakan Amazon Athena, AWS AppSync, dan AWS Amplify untuk membangun aplikasi yang berinteraksi dengan big data. Aplikasi ini dibangun dengan menggunakan React, pustaka Javascript AWS Amplify, dan pustaka Javascript D3.js untuk membuat visualisasi khusus.

Kode aplikasi dapat ditemukan di repositori GitHub ini. Ia menggunakan Athena untuk meminta data yang ditempatkan di Amazon S3 publik oleh Registry of Open Data di AWS. Secara khusus, ia menggunakan Peta Kepadatan Populasi Resolusi Tinggi + Perkiraan Demografis oleh CIESIN dan Facebook.

Dataset publik ini menyediakan “data populasi untuk pilihan negara, dialokasikan untuk 1 blok arcsecond dan disediakan dalam kombinasi berkas CSV dan GeoTIFF yang dioptimalkan untuk Cloud,” dan ditempatkan di bucket S3 s3://dataforgood-fb-data.

Tinjauan Arsitektur

Amplify CLI mengatur proses masuk/pendaftaran dengan Amazon Cognito, membuat API GraphQL untuk operasi GraphQL dan menyediakan penyimpanan konten pada S3 (bucket penyimpanan hasil).

Fitur Amplify CLI Storage Trigger menyediakan fungsi AWS Lambda (fungsi penyiar atau announcer) untuk merespons kejadian dalam bucket hasil. Dengan CLI, izin fungsi penyiar Lambda diatur untuk memungkinkan operasi GraphQL di GraphQL API.

Amplify CLI mendukung penentuan sumber daya khusus yang terkait dengan GraphQL API dengan menggunakan templat AWS CloudFormation AWS CustomResources.json dari Project Amplify, yang terletak di folder amplify/backend/api/YOUR-API-NAME/stacks/. Anda dapat menggunakan kemampuan ini untuk mendefinisikan melalui CloudFormation sumber data HTTP dan resolver AppSync untuk berinteraksi dengan Athena, dan satu sumber data None dan resolver lokal untuk memicu langganan sebagai tanggapan atas mutasi dari fungsi Lambda penyiar (Lambda announcer).

Pengaturan Multi-auth di GraphQL API

AWS AppSync mendukung beberapa mode otorisasi yang dapat digunakan secara bersamaan untuk berinteraksi dengan API. API GraphQL dari aplikasi ini dikonfigurasi dengan Amazon Cognito User Pool sebagai otorisasi secara standar.

Pengguna harus mengautentikasi dengan User Pool sebelum mengirim operasi GraphQL. Setelah saat masuk, pengguna menerima JSON Web Token (JWT) yang dilampirkan pada permintaan di header otorisasi saat mengirim operasi GraphQL.

Otorisasi IAM adalah mode otorisasi lain yang tersedia. API GraphQL dikonfigurasi dengan IAM sebagai mode otorisasi tambahan untuk mengenali dan mengotorisasi permintaan yang ditandatangani SigV4 dari fungsi Lambda penyiar. Konfigurasi dilakukan menggunakan sumber daya khusus yang didukung oleh fungsi Lambda. Sumber daya khusus ini didefinisikan dalam templat CloudFormation dengan AppSyncApiId sebagai properti. Saat dilakukan deployment, ia menggunakan tindakan UpdateGraphqlApi untuk menambahkan mode otorisasi tambahan ke API:

"MultiAuthGraphQLAPI": {
  "Type": "Custom::MultiAuthGraphQLAPIResource",
  "Properties": {
    "ServiceToken": { "Fn::GetAtt": ["MultiAuthGraphQLAPILambda", "Arn"] },
    "AppSyncApiId": { "Ref": "AppSyncApiId" }
  },
  "DependsOn": "MultiAuthGraphQLAPILambda"
}

Skema GraphQL harus menentukan jenis dan atribut mana yang didukung oleh mode otorisasi (dengan Amazon Cognito sebagai konfigurasi standar). Skema ini dikonfigurasi dengan arahan otorisasi yang diperlukan:

  • @aws_iam untuk menentukan apakah ‘field’ atau ‘type’ adalah IAM yang diotorisasi.
  • @aws_cognito_user_pools untuk menentukan apakah suatu ‘field’ atau ‘type’ adalah Cognito Amazon User Pool yang diotorisasi.

Fungsi announcer Lambda membutuhkan akses ke mutasi announceQueryResult dan jenis yang termasuk dalam respons. Jenis AthenaQueryResult dikembalikan oleh permintaan startQuery (dipanggil dari aplikasi), dan dengan announceQueryResult. Jenis ini harus mendukung kedua mode otorisasi.

type AthenaQueryResult @aws_cognito_user_pools @aws_iam {
    QueryExecutionId: ID!
    file: S3Object
}
type S3Object @aws_iam {
    bucket: String!
    region: String!
    key: String!
}
type Query {
    startQuery(input: QueryInput): AthenaQueryResult
}
type Mutation {
    announceQueryResult(input: AnnounceInput!):
      AthenaQueryResult @aws_iam
}

Pengaturan Sumber Data NONE (Resolver Lokal) untuk Mengaktifkan Langganan

Fungsi announcer Lambda dipicu dalam menanggapi peristiwa S3 dan mengirim mutasi GraphQL ke API GraphQL. Mutasi ini kemudian memicu sebuah langganan dan mengirimkan hasil set pilihan mutasi ke aplikasi yang berlangganan.

Data mutasi tidak perlu disimpan. AWS AppSync hanya perlu meneruskan hasil ke aplikasi menggunakan langganan yang dipicu. Untuk mengaktifkan ini, sumber data NONE dikonfigurasikan dan dikaitkan dengan resolver lokal announceQueryResult. Sumber data NONE dan resolver lokal sangat berguna untuk memungkinkan penerbitan langganan waktu-nyata (real-time) tanpa memicu panggilan sumber data untuk mengubah atau memperbarui data.

"DataSourceNone": {
  "Type": "AWS::AppSync::DataSource",
  "Properties": {
    "ApiId": { "Ref": "AppSyncApiId" },
    "Name": "None",
    "Description": "None",
    "Type": "NONE"
  }
},
"AnnounceQueryResultResolver": {
  "Type": "AWS::AppSync::Resolver",
  "Properties": {
    "ApiId": {"Ref": "AppSyncApiId"},
    "DataSourceName": { "Fn::GetAtt": ["DataSourceNone", "Name"] },
    "TypeName": "Mutation",
    "FieldName": "announceQueryResult",
  }
}

Dalam skema, langganan onAnnouncement dikaitkan dengan mutasi.

type Mutation {
    announceQueryResult(input: AnnounceInput!):
      AthenaQueryResult @aws_iam
}
type Subscription {
    onAnnouncement(QueryExecutionId: ID!): 
      AthenaQueryResult
        @aws_subscribe(mutations: ["announceQueryResult"])
}

Pengaturan Athena Sebagai Sumber Data

AWS AppSync mendukung sumber data HTTP dan dapat dikonfigurasi untuk berinteraksi dengan aman dengan titik akhir (endpoint) dari layanan-layanan AWS.

Untuk mengonfigurasi Athena sebagai sumber data, templat CustomResources.json mendefinisikan peran yang digunakan oleh AWS AppSync untuk berinteraksi dengan API: AppSyncAthenaRole.

Peran tersebut dikenakan kebijakan terkelola (managed policy) AmazonAthenaFullAccess. Kebijakan (policy) memberikan izin baca dan tulis ke bucket S3 dengan nama yang dimulai dengan aws-athena-query-results-. Aplikasi menggunakan format ini untuk memberi nama bucket S3 di mana hasil permintaan Athena disimpan. Ini menetapkan policy AmazonS3ReadOnlyAccess untuk memungkinkan Athena membaca dari bucket data sumber.

Sumber daya DataSourceAthenaAPI mendefinisikan sumber data dan menetapkan IAM sebagai jenis otorisasi bersama dengan peran layanan yang akan digunakan.

"AppSyncAthenaRole": {
  "Type": "AWS::IAM::Role",
  "Properties": {
    "RoleName": {
      "Fn::Join": [
        "-",
        ["appSyncAthenaRole", { "Ref": "AppSyncApiId" }, { "Ref": "env" }]
      ]
    },
    "ManagedPolicyArns": [
      "arn:aws:iam::aws:policy/AmazonAthenaFullAccess",
      "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
    ],
    "AssumeRolePolicyDocument": {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": { "Service": ["appsync.amazonaws.com"] },
          "Action": ["sts:AssumeRole"]
        }
      ]
    }
  }
},
"DataSourceAthenaAPI": {
  "Type": "AWS::AppSync::DataSource",
  "Properties": {
    "ApiId": { "Ref": "AppSyncApiId" },
    "Name": "AthenaAPI",
    "Description": "Athena API",
    "Type": "HTTP",
    "ServiceRoleArn": { "Fn::GetAtt": ["AppSyncAthenaRole", "Arn"] },
    "HttpConfig": {
      "Endpoint": {
        "Fn::Join": [
          ".",
          ["https://athena", { "Ref": "AWS::Region" }, "amazonaws.com/"]
        ]
      },
      "AuthorizationConfig": {
        "AuthorizationType": "AWS_IAM",
        "AwsIamConfig": {
          "SigningRegion": { "Ref": "AWS::Region" },
          "SigningServiceName": "athena"
        }
      }
    }
  }
}

Ikhtisar Aplikasi

Berikut ini adalah panduan dan pedoman untuk mengatur aplikasi, mengkonfigurasi langganan, dan visualisasi.

Panduan

Berikut ini cara kerja aplikasi:

  1. Pengguna masuk ke aplikasi menggunakan Amazon Cognito User Pools. Token akses JWT yang dikembalikan saat masuk kemudian dikirim dalam header otorisasi ke AWS AppSync dengan setiap operasi GraphQL.
  2. Seorang pengguna memilih negara dari daftar drop-down dan memilih Query. Ini memicu permintaan GraphQL. Ketika aplikasi menerima QueryExecutionId dalam respons, aplikasi kemudian berlangganan mutasi pada ID tersebut.
  3. AWS AppSync membuat permintaan yang ditandatangani SigV4 ke Athena API dengan permintaan yang ditentukan.
  4. Athena menjalankan kueri terhadap tabel yang ditentukan. Kueri tersebut mengembalikan jumlah populasi pada garis bujur yang direkam untuk negara yang dipilih bersama dengan jumlah garis lintang di setiap garis bujur.
    SELECT longitude, count(latitude) as count, sum(population) as tot_pop
      FROM "default"."hrsl"
      WHERE country='${countryCode.trim()}'
      group by longitude
      order by longitude
  5. Hasil kueri disimpan dalam bucket S3 hasil, dengan awalan /protected/athena/. Pengguna aplikasi yang masuk dapat mengakses hasil ini menggunakan kredensial IAM mereka.
  6. Menempatkan file hasil pertanyaan dalam ember akan menghasilkan peristiwa S3 dan memicu fungsi announcer Lambda.
  7. Fungsi penyiar Lambda mengirimkan mutasi announceQueryResult dengan bucket S3 dan informasi objek.
  8. Mutasi memicu langganan dengan hasil pemilihan dari mutasi.
  9. Klien mengambil berkasi hasil dari bucket S3 dan menampilkan visualisasi khusus.

Pengaturan Aplikasi

Aplikasi ini adalah aplikasi React yang menggunakan pustaka Javascript Amplify untuk berinteraksi dengan layanan backend yang dikonfigurasi oleh Amplify. Untuk memulai, pasang pustaka yang diperlukan.

npm install aws-amplify aws-amplify-react

Kemudian, dalam file aplikasi utama, impor dependensi yang diperlukan, termasuk file ./aws-exports.js yang berisi informasi konfigurasi backend.

import React, { useEffect, useState, useCallback } from 'react'
import Amplify, { API, graphqlOperation, Storage } from 'aws-amplify'
import { withAuthenticator } from 'aws-amplify-react'
...
import awsconfig from './aws-exports'...
Amplify.configure(awsconfig)

Untuk mendapatkan fitur masuk, pendaftaran dan konfirmasi secara otomatis dalam aplikasi, bungkus komponen utama dalam withAuthenticator komponen tingkat tinggi (high-order component / HOC).

export default withAuthenticator(App, true)

Konfigurasi langganan

Ketika pengguna memilih Query, ia memanggil callback startQuery, dan mengirimkan permintaan GraphQL, yang mengembalikan QueryExecutionId dan memperbarui variabel status queryExecutionId.

const [isSending, setIsSending] = useState(false)
const [QueryExecutionId, setQueryExecutionId] = useState(null)

const startQuery = useCallback(async () => {
  if (isSending) return
  setIsSending(true)
  setFileKey(null)
  try {
    const result = await API.graphql(
      graphqlOperation(queries.startQuery, {
        input: { QueryString: sqlQuery(countryCode) }
      })
    )
    console.log(`Setting sub ID: ${result.data.startQuery.QueryExecutionId}`)
    setIsSending(false)
    setQueryExecutionId(result.data.startQuery.QueryExecutionId)
  } catch (error) {
    setIsSending(false)
    console.log('query failed ->', error)
  }
}, [countryCode, isSending])

Pengaturan status akan memicu kait useEffect berikut, yang kemudian membuat sebuah langganan. Setiap kali subscriptionId berubah (misalnya, diatur ke null), ia memanggil fungsi kembalian useEffect, yang berhenti berlangganan dari langganan yang ada.

const [countryCode, setCountryCode] = useState('')
const [fileKey, setFileKey] = useState(null)

useEffect(() => {
  if (!QueryExecutionId) return

  console.log(`Starting subscription with sub ID ${QueryExecutionId}`)
  const subscription = API.graphql(
    graphqlOperation(subscriptions.onAnnouncement, { QueryExecutionId })
  ).subscribe({
    next: result => {
      console.log('subscription:', result)
      const data = result.value.data.onAnnouncement
      console.log('subscription data:', data)
      setFileKey(data.file.key)
      setQueryExecutionId(null)
    }
  })

Visualisasi

Ketika dipicu, langganan onAnnouncement mengembalikan data berikut yang ditentukan dalam set pilihan mutasi. Ini memberi tahu aplikasi tempat mengambil file hasil. Pengguna yang sign-in dapat membaca objek di keranjang hasil dimulai dengan /protected/ awalan. Karena Athena menyimpan hasil di bawah /protected/athena/ prefix, pengguna yang diautentikasi dapat mengambil berkas hasil.

QueryExecutionId
    file {
        bucket
        region
        key
}

Nilai kunci diserahkan ke properti fileKey dalam komponen Visuals. Aplikasi membagi kunci untuk mengekstraksi level (protected), identitas (Athena), dan kunci objek (\*.csv). Fungsi Storage.get menghasilkan URL presigned dengan kredensial IAM, digunakan untuk mengambil file dengan fungsi d3.csv.

File ini adalah file CSV dengan baris bujur, jumlah, dan populasi. Sebuah callback akan memetakan nilai ke x dan y (koordinat grafik), dan atribut count. Aplikasi ini menggunakan pustaka D3.js bersama dengan plugin d3-hexbin untuk membuat visualisasi. Plugin d3-hexbin mengelompokkan titik data dalam wadah berbentuk heksagonal berdasarkan radius yang ditentukan.

const [link, setLink] = useState(null)
useEffect(() => {
  const go = async () => {
    const [level, identityId, _key] = fileKey.split('/')
    const link = await Storage.get(_key, { level, identityId })
    setLink(link)

    const data = Object.assign(
      await d3.csv(link, ({ longitude, tot_pop, count }) => ({
        x: parseFloat(longitude),
        y: parseFloat(tot_pop),
        count: parseInt(count)
      })),
      { x: 'Longitude', y: 'Population', title: 'Pop bins by Longitude' }
    )
    drawChart(data)
  }
  go()
}, [fileKey])

Meluncurkan Aplikasi

Ikuti langkah-langkah ini untuk meluncurkan aplikasi.

Peluncuran satu klik

Anda dapat menggunakan aplikasi secara langsung ke Amplify Console dari repositori GitHub publik. Infrastruktur backend dan aplikasi frontend sudah dibangun dan dipasang. Setelah aplikasi dipasang, ikuti langkah-langkah yang tersisa untuk mengkonfigurasi basisdata Athena anda.

Salin dan Luncurkan

Sebagai alternatif, anda dapat menyalin repositori, meluncurkan backend dengan Amplify CLI, dan membangun dan melayani frontend secara lokal.

Pertama, pasang Amplify CLI dan lewati konfigurasi.

$ npm install -g @aws-amplify/cli
$ amplify configure

Selanjutnya, salin repositori dan pasang dependensi.

$ git clone https://github.com/aws-samples/aws-appsync-visualization-with-athena-app
$ cd aws-appsync-visualization-with-athena-app
$ yarn

Perbarui nama bucket penyimpanan (bucketName) dalam file ./amplify/backend/storage/sQueryResults/parameters.json lalu inisialisasi proyek Amplify baru dan dorong perubahan.

$ amplify init
$ amplify push

Akhirnya, luncurkan aplikasi.

$ yarn start

Mempersiapkan Athena

Aplikasi menggunakan data yang disimpan di S3 oleh Registry of Open Data di AWS. Khususnya, Anda menggunakan Peta Kepadatan Populasi Resolusi Tinggi + Perkiraan Demografis oleh CIESIN dan Facebook. Anda dapat menemukan informasi tentang cara mengatur Athena untuk mengambil dataset ini dalam berkas Readme.

Dari Konsol Athena:

  1. Buat basisdata bernama default.
    create database IF NOT EXISTS default;
  2. Buat tabel di basisdata default.
    CREATE EXTERNAL TABLE IF NOT EXISTS default.hrsl (
      `latitude` double,
      `longitude` double,
      `population` double
    ) PARTITIONED BY (
      month string,
      country string,
      type string
    ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
    WITH SERDEPROPERTIES (
      'serialization.format' = '\t',
      'field.delim' = '\t'
    ) LOCATION 's3://dataforgood-fb-data/csv/'
    TBLPROPERTIES ('has_encrypted_data'='false', 'skip.header.line.count'='1');
  3. Pulihkan partisi.
    MSCK REPAIR TABLE hrsl;

    Bila selesai, Anda seharusnya dapat melihat pratinjau tabel dan melihat jenis informasi yang ditunjukkan pada tangkapan layar berikut.|

  4. Terakhir, buat workgroup baru. Pertama, cari nama bucket penyimpanan konten S3 Anda.
    • Jika Anda menggunakan peluncuran satu klik, cari aws_user_files_s3_bucket di log aktivitas backend yang tersedia dengan mengklik tombol Download di bagian Build Activity dari konsol Amplify.
    • Jika anda menggunakan langkah-langkah “Salin dan Luncurkan”, temukan aws_user_files_s3_bucket di file aws-exports.js Anda di direktori src.

Dari konsol Athena, pilih Workgroup di bagian atas, lalu pilih Create workgroup. Berikan nama workgroup: appsync. Konfigurasi Query result location ke s3://BUCKET_NAME/protected/athena/. Pilih Create workgroup.

Kesimpulan

Tulisan ini menunjukkan cara menggunakan AWS AppSync untuk berinteraksi dengan Amazon Athena API dan membuat visualisasi khusus secara aman di aplikasi frontend Anda. Dengan menggabungkan layanan ini, anda dapat dengan mudah membuat aplikasi yang berinteraksi langsung dengan big data yang disimpan di S3, dan menyajikan data dalam berbagai cara dengan grafik dan bagan.

Bersama dengan pustaka D3.js, Anda dapat mengembangkan cara inovatif baru untuk berinteraksi dengan data dan menampilkan informasi kepada pengguna. Selain itu, Anda dapat memulai dengan cepat, mengimplementasikan fungsi-fungsi utama, dan melakukan penerapan (deployment) secara instan menggunakan AWS Amplify Framework.

Anda ingin mengetahui lebih lanjut bagaimana perusahaan Anda bisa mengimplementasikan AWS AppSync, Amazon Athena, dan AWS Amplify untuk visualisasi data Anda, Anda bisa berbicara dengan tim kami.


Tulisan ini berasal dari artikel Visualizing big data with AWS AppSync, Amazon Athena, and AWS Amplify yang ditulis oleh Brice Pelle dan diterjemahkan oleh Paul Chen.

Petra Barus

Petra Barus

Petra Novandi Barus is Developer Advocate at Amazon Web Services based in Jakarta. He is passionate in helping startups and developers in Indonesia to reinvent on behalf their customers. Prior to AWS, Petra co-founded UrbanIndo.com as CTO. The startup became the largest real-estate portal in Indonesia and then was acquired by 99.co. During that time Petra had been a happy AWS customer for 8 years. Petra is also very active in local tech communities