

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Node.js dan DAX
<a name="DAX.client.run-application-nodejs-3"></a>

# Konfigurasi klien default untuk Node.js
<a name="DAX-client-config-JS"></a>

Saat mengonfigurasi klien DAX JavaScript SDK, Anda dapat menyesuaikan berbagai parameter untuk mengoptimalkan kinerja, penanganan koneksi, dan ketahanan kesalahan. Tabel berikut menguraikan pengaturan konfigurasi default yang mengontrol cara klien Anda berinteraksi dengan klaster DAX, termasuk nilai batas waktu, mekanisme coba lagi, manajemen kredensi, dan opsi pemantauan kesehatan. Untuk informasi selengkapnya, lihat [DBClient Operasi Dynamo](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/).


**Default klien DAX JS SDK**  

| Parameter | Jenis | Deskripsi | 
| --- | --- | --- | 
|  `region` opsional  |  `string`  |   Wilayah AWS Untuk digunakan untuk klien DAX (contoh - 'us-east-1'). Ini adalah parameter yang diperlukan jika tidak disediakan melalui variabel lingkungan.  | 
|  `endpoint` wajib  |  `string`  | Titik akhir Cluster yang terhubung dengan SDK. Contoh: Tidak terenkripsi — .region.amazonaws.com dax-cluster-name Terenkripsi - daxs: //my-cluster.l6fzcv. dax-clusters.us-east-1.amazonaws.com  | 
|  `requestTimeout` default 6000 ms  |  `number`  | Ini menentukan waktu maksimum klien akan menunggu respons dari DAX.  | 
|  `writeRetries` default 1  |  `number`  | Jumlah percobaan ulang untuk mencoba permintaan tulis yang gagal.  | 
|  `readRetries` default 1  |  `number`  | Jumlah percobaan ulang untuk mencoba permintaan baca yang gagal.  | 
|  `maxRetries` default 1  |  `number`  | Jumlah maksimum percobaan ulang untuk mencoba permintaan yang gagal. Jika readRetries/writeRetries disetel, maka konfigurasi yang disetel di ReadRetries dan WriteRetries diprioritaskan daripada maxRetries.  | 
|  `connectTimeout` default 10000 ms  |  `number`  | Batas waktu (dalam milidetik) untuk membuat koneksi ke salah satu node cluster.  | 
|  `maxConcurrentConnections` standar 100  |  `number`  | Membatasi jumlah total koneksi bersamaan yang dapat dibuat oleh instance klien per node dalam cluster DAX.  | 
|  `maxRetryDelay` default 7000 ms  |  `number`  | Ketika server DAX menunjukkan pemulihan diperlukan dengan menyetel `waitForRecoveryBeforeRetrying` flag ke true, klien akan berhenti sebelum mencoba lagi. Selama periode pemulihan ini, `maxRetryDelay` parameter menentukan waktu tunggu maksimum antara percobaan ulang. Konfigurasi khusus pemulihan ini hanya berlaku ketika server DAX dalam mode pemulihan. Untuk semua skenario lainnya, perilaku coba lagi mengikuti salah satu dari dua pola: baik penundaan eksponensial berdasarkan jumlah coba lagi (diatur oleh`writeRetries`,, atau `maxRetries` parameter)`readRetries`, atau coba lagi langsung tergantung pada jenis pengecualian.  | 
|  `credentials` opsional  |  `[AwsCredentialIdentity](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/)` \$1 `[AwsCredentialIdentityProvider](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/)`  |   AWS Kredensyal yang digunakan untuk mengautentikasi permintaan. Ini dapat diberikan sebagai AwsCredentialIdentity atau AwsCredentialIdentityProvider. Jika tidak disediakan, AWS SDK akan secara otomatis menggunakan rantai penyedia kredensi default. Contoh: `\$1 accessKeyId: 'AKIA... ' , secretAccessKey: ' ... ', SessionToken:'... '\$1 `\$1 @default Menggunakan rantai penyedia kredensi AWS default.  | 
|  `healthCheckInterval` default 5000 ms  |  `number`  | Interval (dalam milidetik) antara pemeriksaan kesehatan cluster. Interval yang lebih rendah akan lebih sering diperiksa.  | 
|  `healthCheckTimeout` default 1000 ms  |  `number`  | Batas waktu (dalam milidetik) untuk pemeriksaan kesehatan selesai.  | 
|  `skipHostnameVerification` default palsu  |  `boolean`  |  Lewati verifikasi nama host koneksi TLS. Ini tidak berdampak pada cluster yang tidak terenkripsi. Standarnya adalah melakukan verifikasi nama host, menyetel ini ke True akan melewati verifikasi. Pastikan Anda memahami implikasi dari mematikannya, yang merupakan ketidakmampuan untuk mengotentikasi cluster yang Anda sambungkan.   | 
|  `unhealthyConsecutiveErrorCount` default 5  |  `number`  | Menetapkan jumlah kesalahan berturut-turut yang diperlukan untuk memberi sinyal node tidak sehat dalam interval pemeriksaan kesehatan.  | 
|  `clusterUpdateInterval` default 4000 ms  |  `number`  | Mengembalikan interval antara polling anggota cluster untuk perubahan keanggotaan.  | 
|  `clusterUpdateThreshold` standar 125  |  `number`  | Mengembalikan ambang batas di bawah mana cluster tidak akan disurvei untuk perubahan keanggotaan.  | 
|  `credentailProvider` opsional \$1 default null  |  `[AwsCredentialIdentityProvider](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/)`  | Penyedia yang Ditetapkan Pengguna untuk AWS kredensil yang digunakan untuk mengautentikasi permintaan ke DAX.  | 


**Konfigurasi pagination untuk DaxDocument**  

| Nama | Tipe | Detail | 
| --- | --- | --- | 
|  `client`  |  DaxDocument  |  Contoh DaxDocument tipe.  | 
|  `pageSize`  |  number  |  Menentukan jumlah item per halaman.  | 
|  `startingToken` Opsional  |  any  |  LastEvaluatedKey dari tanggapan sebelumnya dapat digunakan untuk permintaan berikutnya.  | 

Untuk penggunaan pagination, lihat[TryDax.js](DAX.client.tutorial-TryDax.md).

# Migrasi ke DAX Node.js SDK V3
<a name="DAX.client.run-application-nodejs-3-migrating"></a>

Panduan migrasi ini akan membantu Anda mentransisikan aplikasi DAX Node.js yang ada. SDK baru memerlukan Node.js 18 atau lebih tinggi dan memperkenalkan beberapa perubahan penting dalam cara Anda menyusun kode DynamoDB Accelerator Anda. Panduan ini akan memandu Anda melalui perbedaan utama, termasuk perubahan sintaks, metode impor baru, dan pola pemrograman asinkron yang diperbarui.

## V2 Node.js penggunaan DAX
<a name="DAX.client.run-application-nodejs-3-migrating-V2-usage"></a>

```
const AmazonDaxClient = require('amazon-dax-client');
const AWS = require('aws-sdk');

var region = "us-west-2";

AWS.config.update({
  region: region,
});

var client = new AWS.DynamoDB.DocumentClient();

if (process.argv.length > 2) {
  var dax = new AmazonDaxClient({
    endpoints: [process.argv[2]],
    region: region,
  });
  client = new AWS.DynamoDB.DocumentClient({ service: dax });
}

// Make Get Call using Dax
var params = {
    TableName: 'TryDaxTable',
    pk: 1,
    sk: 1
}
client.get(params, function (err, data) {
    if (err) {
        console.error(
            "Unable to read item. Error JSON:",
            JSON.stringify(err, null, 2)
          );
    } else {
        console.log(data);
    }
});
```

## Penggunaan V3 Node.js DAX
<a name="DAX.client.run-application-nodejs-3-migrating-V3-dax-usage"></a>

Untuk Menggunakan DAX Node.js V3 Node versi 18 atau lebih tinggi adalah versi yang disukai. Untuk pindah ke Node 18, gunakan yang berikut ini:

```
import { DaxDocument } from '@amazon-dax-sdk/lib-dax';
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

let client: DynamoDBDocument | DaxDocument = DynamoDBDocument.from(
  new DynamoDBClient({ region: 'us-west-2' })
);

if (process.argv.length > 2) {
  client = new DaxDocument({
    endpoints: [process.argv[2]],
    region: 'us-west-2',
  });
}

const params = {
  TableName: 'TryDaxTable',
  Key: { pk: 1, sk: 1 },
};

try {
  const results = await client.get(params);
  console.log(results);
} catch (err) {
  console.error(err);
}
```

DAX SDK untuk Node.js v3.x kompatibel dengan [AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/) untuk Node.js v3.x. [DAX SDK untuk Node.js v3.x mendukung penggunaan klien agregat.](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/#high-level-concepts) Harap dicatat bahwa DAX tidak mendukung pembuatan klien telanjang. Untuk detail selengkapnya tentang fitur yang tidak didukung, lihat[Fitur tidak paritas dengan AWS SDK V3](#DAX.client.run-application-nodejs-3-not-in-parity).

Ikuti langkah-langkah berikut untuk menjalankan aplikasi sampel Node.js pada instans Amazon EC2 Anda.

**Cara menjalankan sampel Node.js untuk DAX**

1. Atur Node.js pada instans Amazon EC2 Anda sebagai berikut:

   1. Instal manajer versi simpul (`nvm`).

      ```
      curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
      ```

   1. Gunakan nvm untuk menginstal Node.js.

      ```
      nvm install 18
      ```

   1. Gunakan nvm untuk menggunakan Node 18

      ```
      nvm use 18
      ```

   1. Pastikan bahwa Node.js sudah diinstal dan berjalan dengan benar.

      ```
      node -e "console.log('Running Node.js ' + process.version)"
      ```

      Tindakan ini akan menampilkan pesan berikut.

      `Running Node.js v18.x.x`

1. Instal klien DaxDocument Node.js menggunakan node package manager (`npm`).

   ```
   npm install @amazon-dax-sdk/lib-dax
   ```

## TryDax kode sampel
<a name="DAX.client.run-application-nodejs-3-TryDax-sample-code"></a>

Untuk mengevaluasi manfaat kinerja DynamoDB Accelerator (DAX), ikuti langkah-langkah berikut untuk menjalankan pengujian sampel yang membandingkan waktu operasi baca antara DynamoDB standar dan cluster DAX.

1. Setelah Anda menyiapkan ruang kerja dan menginstal dependensi `lib-dax` sebagai dependensi, salin [TryDax.js](DAX.client.tutorial-TryDax.md) ke proyek Anda.

1. Jalankan program terhadap cluster DAX Anda. Untuk menentukan titik akhir klaster DAX Anda, pilih salah satu dari berikut ini: 
   +  **Menggunakan konsol DynamoDB** — Pilih klaster DAX Anda. Titik akhir klaster ditampilkan pada konsol, seperti dalam contoh berikut.

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **Menggunakan AWS CLI** — Masukkan perintah berikut.

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     Titik akhir klaster ditampilkan pada output, seperti dalam contoh berikut.

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

1. Sekarang jalankan program dengan menentukan titik akhir cluster sebagai parameter baris perintah.

   ```
   node TryDax.js dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   ```

   Anda akan melihat output yang serupa dengan yang berikut:

   ```
   Attempting to create table; please wait...
   Successfully created table. Table status: ACTIVE
   Writing data to the table...
   Writing 20 items for partition key:  1
   Writing 20 items for partition key:  2
   Writing 20 items for partition key:  3
   ...
   Running GetItem Test
           Total time: 153555.10 µs - Avg time: 383.89 µs
           Total time: 44679.96 µs - Avg time: 111.70 µs
           Total time: 36885.86 µs - Avg time: 92.21 µs
           Total time: 32467.25 µs - Avg time: 81.17 µs
           Total time: 32202.60 µs - Avg time: 80.51 µs
   Running Query Test
           Total time: 14869.25 µs - Avg time: 2973.85 µs
           Total time: 3036.31 µs - Avg time: 607.26 µs
           Total time: 2468.92 µs - Avg time: 493.78 µs
           Total time: 2062.53 µs - Avg time: 412.51 µs
           Total time: 2178.22 µs - Avg time: 435.64 µs
   Running Scan Test
           Total time: 2395.88 µs - Avg time: 479.18 µs
           Total time: 2207.16 µs - Avg time: 441.43 µs
           Total time: 2443.14 µs - Avg time: 488.63 µs
           Total time: 2038.24 µs - Avg time: 407.65 µs
           Total time: 1972.17 µs - Avg time: 394.43 µs
   Running Pagination Test
   Scan Pagination
   [
     { pk: 1, sk: 1, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 2, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 3, someData: 'XXXXXXXXXX' }
   ]
   [
     { pk: 1, sk: 4, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 5, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 6, someData: 'XXXXXXXXXX' }
   ]
   ...
   Query Pagination
   [
     { pk: 1, sk: 1, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 2, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 3, someData: 'XXXXXXXXXX' }
   ]
   [
     { pk: 1, sk: 4, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 5, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 6, someData: 'XXXXXXXXXX' }
   ]
   ...
   Attempting to delete table; please wait...
   Successfully deleted table.
   ```

   Catat informasi waktu. Jumlah mikrodetik yang diperlukan untuk`GetItem`,`Query`, `Scan` tes.

1. Dalam hal ini, Anda menjalankan program terhadap cluster DAX. Sekarang, Anda akan menjalankan program lagi, kali ini melawan DynamoDB.

1. Sekarang jalankan program lagi, tapi kali ini, tanpa URL endpoint cluster sebagai parameter baris perintah.

   ```
   node TryDax.js
   ```

   Lihat output dan perhatikan informasi waktu. Waktu yang telah berlalu untuk`GetItem`,`Query`, dan `Scan` harus jauh lebih rendah dengan DAX dibandingkan dengan DynamoDB.

## Fitur tidak paritas dengan AWS SDK V3
<a name="DAX.client.run-application-nodejs-3-not-in-parity"></a>
+ Klien [telanjang -](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/#high-level-concepts) Dax Node.js V3 tidak mendukung klien telanjang. 

  ```
  const dynamoDBClient = new DynamoDBClient({ region: 'us-west-2' });
  const regularParams = {
      TableName: 'TryDaxTable',
      Key: {
          pk: 1,
          sk: 1
      }
  };
  // The DynamoDB client supports the send operation.
  const dynamoResult = await dynamoDBClient.send(new GetCommand(regularParams));
  
  // However, the DaxDocument client does not support the send operation.
  const daxClient = new DaxDocument({
      endpoints: ['your-dax-endpoint'],
      region: 'us-west-2',
  });
  
  const params = {
      TableName: 'TryDaxTable',
      Key: {
          pk: 1,
          sk: 1
      }
  };
  
  // This will throw an error - send operation is not supported for DAX. Please refer to documentation.
  const result = await daxClient.send(new GetCommand(params));
  console.log(result);
  ```
+ [Middleware Stack](https://aws.amazon.com/blogs/developer/middleware-stack-modular-aws-sdk-js/) - Dax Node.js V3 tidak mendukung penggunaan fungsi Middleware.

  ```
  const dynamoDBClient = new DynamoDBClient({ region: 'us-west-2' });
  // The DynamoDB client supports the middlewareStack.
  dynamoDBClient.middlewareStack.add(
    (next, context) =>> async (args) => {
      console.log("Before operation:", args);
      const result = await next(args);
      console.log("After operation:", result);
      return result;
    },
    {
      step: "initialize", // or "build", "finalizeRequest", "deserialize"
      name: "loggingMiddleware",
    }
  );
  
  // However, the DaxDocument client does not support the middlewareStack.
  const daxClient = new DaxDocument({
      endpoints: ['your-dax-endpoint'],
      region: 'us-west-2',
  });
  
  // This will throw an error - custom middleware and middlewareStacks are not supported for DAX. Please refer to documentation.
  daxClient.middlewareStack.add(
    (next, context) => async (args) => {
      console.log("Before operation:", args);
      const result = await next(args);
      console.log("After operation:", result);
      return result;
    },
    {
      step: "initialize", // or "build", "finalizeRequest", "deserialize"
      name: "loggingMiddleware",
    }
  );
  ```

# TryDax.js
<a name="DAX.client.tutorial-TryDax"></a>

```
import { DynamoDB, waitUntilTableExists, waitUntilTableNotExists } from "@aws-sdk/client-dynamodb";
import { DaxDocument, daxPaginateScan, daxPaginateQuery } from "@amazon-dax-sdk/lib-dax";
import { DynamoDBDocument, paginateQuery, paginateScan } from "@aws-sdk/lib-dynamodb";

const region = "us-east-1";
const tableName = "TryDaxTable";

// Determine the client (DynamoDB or DAX)
let client = DynamoDBDocument.from(new DynamoDB({ region }));
if (process.argv.length > 2) {
  client = new DaxDocument({ region, endpoint: process.argv[2] });
}

// Function to create table
async function createTable() {
  const dynamodb = new DynamoDB({ region });
  const params = {
    TableName: tableName,
    KeySchema: [
      { AttributeName: "pk", KeyType: "HASH" },
      { AttributeName: "sk", KeyType: "RANGE" },
    ],
    AttributeDefinitions: [
      { AttributeName: "pk", AttributeType: "N" },
      { AttributeName: "sk", AttributeType: "N" },
    ],
    ProvisionedThroughput: { ReadCapacityUnits: 25, WriteCapacityUnits: 25 },
  };

  try {
    console.log("Attempting to create table; please wait...");
    await dynamodb.createTable(params);
    await waitUntilTableExists({ client: dynamodb, maxWaitTime: 30 }, { TableName: tableName });
    console.log("Successfully created table. Table status: ACTIVE");
  } catch (err) {
    console.error("Error in table creation:", err);
  }
}

// Function to insert data
async function writeData() {
  console.log("Writing data to the table...");
  const someData = "X".repeat(10);
  for (let ipk = 1; ipk <= 20; ipk++) {
    console.log("Writing 20 items for partition key: ", ipk)
    for (let isk = 1; isk <= 20; isk++) {
      try {
        await client.put({ TableName: tableName, Item: { pk: ipk, sk: isk, someData } });
      } catch (err) {
        console.error("Error inserting data:", err);
      }
    }
  }
}

// Function to test GetItem
async function getItemTest() {
  console.log("Running GetItem Test");
  for (let i = 0; i < 5; i++) {
    const startTime = performance.now();
    const promises = [];
    for (let ipk = 1; ipk <= 20; ipk++) {
      for (let isk = 1; isk <= 20; isk++) {
        promises.push(client.get({ TableName: tableName, Key: { pk: ipk, sk: isk } }));
      }
    }
    await Promise.all(promises);
    const endTime = performance.now();
    const iterTime = (endTime - startTime) * 1000;
    const totalTime = iterTime.toFixed(2).padStart(3, ' ');
    const avgTime = (iterTime / 400).toFixed(2).padStart(3, ' ');
    console.log(`\tTotal time: ${totalTime} \u00B5s - Avg time: ${avgTime} \u00B5s`);
  }
}

// Function to test Query
async function queryTest() {
  console.log("Running Query Test");
  for (let i = 0; i < 5; i++) {
    const startTime = performance.now();
    const promises = [];
    for (let pk = 1; pk <= 5; pk++) {
      const params = {
        TableName: tableName,
        KeyConditionExpression: "pk = :pkval and sk between :skval1 and :skval2",
        ExpressionAttributeValues: { ":pkval": pk, ":skval1": 1, ":skval2": 2 },
      };
      promises.push(client.query(params));
    }
    await Promise.all(promises);
    const endTime = performance.now();
    const iterTime = (endTime - startTime) * 1000;
    const totalTime = iterTime.toFixed(2).padStart(3, ' ');
    const avgTime = (iterTime / 5).toFixed(2).padStart(3, ' ');
    console.log(`\tTotal time: ${totalTime} \u00B5s - Avg time: ${avgTime} \u00B5s`);
  }
}

// Function to test Scan
async function scanTest() {
  console.log("Running Scan Test");
  for (let i = 0; i < 5; i++) {
    const startTime = performance.now();
    const promises = [];
    for (let pk = 1; pk <= 5; pk++) {
      const params = {
        TableName: tableName,
        FilterExpression: "pk = :pkval and sk between :skval1 and :skval2",
        ExpressionAttributeValues: { ":pkval": pk, ":skval1": 1, ":skval2": 2 },
      };
      promises.push(client.scan(params));
    }
    await Promise.all(promises);
    const endTime = performance.now();
    const iterTime = (endTime - startTime) * 1000;
    const totalTime = iterTime.toFixed(2).padStart(3, ' ');
    const avgTime = (iterTime / 5).toFixed(2).padStart(3, ' ');
    console.log(`\tTotal time: ${totalTime} \u00B5s - Avg time: ${avgTime} \u00B5s`);
  }
}

// Function to test Pagination
async function paginationTest() {
  console.log("Running Pagination Test");
  console.log("Scan Pagination");
  const scanParams = { TableName: tableName };
  const paginator = process.argv.length > 2 ? daxPaginateScan : paginateScan;
  for await (const page of paginator({ client, pageSize: 3 }, scanParams)) {
    console.log(page.Items);
  }

  console.log("Query Pagination");
  const queryParams = {
    TableName: tableName,
    KeyConditionExpression: "pk = :pkval and sk between :skval1 and :skval2",
    ExpressionAttributeValues: { ":pkval": 1, ":skval1": 1, ":skval2": 10 },
  };
  const queryPaginator = process.argv.length > 2 ? daxPaginateQuery : paginateQuery;
  for await (const page of queryPaginator({ client, pageSize: 3 }, queryParams)) {
    console.log(page.Items);
  }
}

// Function to delete the table
async function deleteTable() {
  const dynamodb = new DynamoDB({ region });
  console.log("Attempting to delete table; please wait...")
  try {
    await dynamodb.deleteTable({ TableName: tableName });
    await waitUntilTableNotExists({ client: dynamodb, maxWaitTime: 30 }, { TableName: tableName });
    console.log("Successfully deleted table.");
  } catch (err) {
    console.error("Error deleting table:", err);
  }
}

// Execute functions sequentially
(async function () {
  await createTable();
  await writeData();
  await getItemTest();
  await queryTest();
  await scanTest();
  await paginationTest();
  await deleteTable();
})();
```