<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Engineering @ ShopBase]]></title><description><![CDATA[Engineering @ ShopBase]]></description><link>https://engineering.shopbase.com/</link><image><url>https://engineering.shopbase.com/favicon.png</url><title>Engineering @ ShopBase</title><link>https://engineering.shopbase.com/</link></image><generator>Ghost 5.76</generator><lastBuildDate>Sat, 09 May 2026 03:41:38 GMT</lastBuildDate><atom:link href="https://engineering.shopbase.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[[TIL] Gửi mail trong PHP bằng Gmail]]></title><description><![CDATA[<p>H&#xF4;m tr&#x1B0;&#x1EDB;c m&#xEC;nh v&#x1EDB;i T&#xF9;ng l&#xE0;m con app c&#xF3; ph&#x1EA7;n g&#x1EED;i mail, &#x111;&#x1ECB;nh d&#xF9;ng SNS c&#x1EE7;a AWS m&#xE0; c&#xF3; v&#x1EBB; kh&#xF4;ng</p>]]></description><link>https://engineering.shopbase.com/til-gui-mail-trong-php-bang-gmail/</link><guid isPermaLink="false">6602e0c50b0ab5bbc6d70bbf</guid><dc:creator><![CDATA[Phong Do]]></dc:creator><pubDate>Tue, 26 Mar 2024 14:52:39 GMT</pubDate><content:encoded><![CDATA[<p>H&#xF4;m tr&#x1B0;&#x1EDB;c m&#xEC;nh v&#x1EDB;i T&#xF9;ng l&#xE0;m con app c&#xF3; ph&#x1EA7;n g&#x1EED;i mail, &#x111;&#x1ECB;nh d&#xF9;ng SNS c&#x1EE7;a AWS m&#xE0; c&#xF3; v&#x1EBB; kh&#xF4;ng gi&#xF2;n l&#x1EAF;m, b&#x1EAF;t x&#xE1;c th&#x1EF1;c linh tinh. B&#x1EF1;c m&#xEC;nh, t&#x1EF1; code m&#x1ECB;a cho nhanh.</p><p>Sau &#x111;&#xE2;y l&#xE0; c&#xE1;ch code b&#x1EB1;ng PHP.</p><h2 id="b%C6%B0%E1%BB%9Bc-1-t%E1%BA%A1o-app-password-cho-gmail">B&#x1B0;&#x1EDB;c 1: T&#x1EA1;o app password cho gmail.</h2><p>Y&#xEA;u c&#x1EA7;u: t&#xE0;i kho&#x1EA3;n c&#x1EE7;a b&#x1EA1;n &#x111;&#xE3; b&#x1EAD;t 2FA.</p><ul><li>Truy c&#x1EAD;p: <a href="https://myaccount.google.com/apppasswords?ref=engineering.shopbase.com">https://myaccount.google.com/apppasswords</a> ho&#x1EB7;c search App Password t&#x1EA1;i trang myaccount c&#x1EE7;a Google.</li></ul><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2024/03/create-app-password-01.png?w=1024" class="kg-image" alt loading="lazy"></figure><ul><li>Nh&#x1EAD;p t&#xEA;n cho App password</li></ul><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2024/03/create-app-password-02.png?w=1010" class="kg-image" alt loading="lazy"></figure><ul><li>Sau khi t&#x1EA1;o xong s&#x1EBD; hi&#x1EC7;n ra 1 c&#xE1;i popup c&#xF3; ch&#x1EE9;a password. B&#x1EA1;n l&#x1B0;u l&#x1EA1;i password n&#xE0;y</li></ul><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2024/03/create-app-password-03.png?w=789" class="kg-image" alt loading="lazy"></figure><h2 id="b%C6%B0%E1%BB%9Bc-2-th%C3%AAm-code-php">B&#x1B0;&#x1EDB;c 2: Th&#xEA;m code PHP</h2><ul><li>D&#xF9;ng composer, c&#xE0;i PHPMailer:</li></ul><pre><code>composer require phpmailer/phpmailer</code></pre><p>Ho&#x1EB7;c kh&#xF4;ng th&#xEC; b&#x1EA1;n v&#xE0;o repo g&#x1ED1;c, down v&#x1EC1;: <a href="https://github.com/PHPMailer/PHPMailer?ref=engineering.shopbase.com">https://github.com/PHPMailer/PHPMailer</a></p><ul><li>Th&#xEA;m code g&#x1EED;i mail</li></ul><pre><code class="language-PHP">&lt;?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// Setting response header json
header(&apos;Content-Type: application/json&apos;);

// Check if not post method -&gt; throw error
if ($_SERVER[&apos;REQUEST_METHOD&apos;] !== &apos;POST&apos;) {
  http_response_code(405);
  echo json_encode([&apos;error&apos; =&gt; &apos;Method not allowed&apos;]);
  exit();
}

// Decode json body
$body = json_decode(file_get_contents(&apos;php://input&apos;), true);

// Check if missing email -&gt; throw error
if (!isset($body[&apos;email&apos;])) {
  http_response_code(400);
  echo json_encode([&apos;error&apos; =&gt; &apos;Missing email&apos;]);
  exit();
}

// Check if missing subject -&gt; throw error
if (!isset($body[&apos;subject&apos;])) {
  http_response_code(400);
  echo json_encode([&apos;error&apos; =&gt; &apos;Missing subject&apos;]);
  exit();
}

// Check if missing message -&gt; throw error
if (!isset($body[&apos;message&apos;])) {
  http_response_code(400);
  echo json_encode([&apos;error&apos; =&gt; &apos;Missing message&apos;]);
  exit();
}

try {
  // if (isset($_POST[&apos;submit&apos;])) {
    $mailData = [
      &apos;email&apos; =&gt; $body[&apos;email&apos;],
      &apos;subject&apos; =&gt; $body[&apos;subject&apos;],
      &apos;message&apos; =&gt; $body[&apos;message&apos;]
    ];
  
    require &apos;vendor/autoload.php&apos;;
  
    $mail = new PHPMailer();
    $mail-&gt;isSMTP();
    $mail-&gt;Host = &apos;smtp.gmail.com&apos;;
    $mail-&gt;SMTPAuth = true;
    $mail-&gt;Username = &apos;youremail@gmail&apos;;
    $mail-&gt;Password = &apos;app_password&apos;;
    $mail-&gt;SMTPSecure = &apos;tls&apos;;
    $mail-&gt;Port = 587;
  
    $mail-&gt;setFrom(&apos;fromemail&apos;, &quot;Minh Phong 306 Blog&quot;);
    $mail-&gt;addAddress($mailData[&apos;email&apos;], &apos;User&apos;);
    $mail-&gt;isHTML(true);
  
    $mail-&gt;Subject = $mailData[&apos;subject&apos;];
    $mail-&gt;Body = $mailData[&apos;message&apos;];
    $mail-&gt;AltBody = &apos;Alt body&apos;;
    $mail-&gt;send();
    
    echo json_encode([&apos;message&apos; =&gt; &apos;Message has been sent&apos;]);
  // }
} catch (Exception $ex) {
  echo &apos;Message could not be sent. Mailer Error: &apos;, $mail-&gt;ErrorInfo;
}
</code></pre><ul><li>Anh em l&#x1B0;u &#xFD;:<ul><li>App password: nh&#x1EDB; b&#x1ECF; kho&#x1EA3;ng tr&#x1EAF;ng &#x111;i, n&#xF3; l&#xE0; 16 k&#xED; t&#x1EF1; li&#x1EC1;n nhau.</li><li>$mail-&gt;Username&#xA0;=&#xA0;&apos;youremail@gmail&apos;; ~&gt; &#x111;o&#x1EA1;n n&#xE0;y set email g&#x1EED;i &#x111;i</li><li>$mail-&gt;Password = &apos;app_password&apos;; ~&gt; &#x111;o&#x1EA1;n n&#xE0;y l&#xE0; app pwd t&#x1EA1;o &#x1EDF; b&#x1B0;&#x1EDB;c 1</li><li>$mail-&gt;setFrom(&apos;fromemail&apos;, &quot;Minh Phong 306 Blog&quot;); ~&gt; &#x111;o&#x1EA1;n n&#xE0;y set hi&#x1EC3;n th&#x1ECB; &#x1EDF; ch&#x1ED7; ng&#x1B0;&#x1EDD;i g&#x1EED;i l&#xE0; mail &#x111;ang g&#x1EED;i t&#x1EEB; &#x111;&#xE2;u &#x111;i v&#xE0; t&#xEA;n ng&#x1B0;&#x1EDD;i g&#x1EED;i l&#xE0; g&#xEC;.</li><li>$mail-&gt;addAddress($mailData[&apos;email&apos;], &apos;User&apos;); ~&gt; &#x110;o&#x1EA1;n n&#xE0;y set email ng&#x1B0;&#x1EDD;i nh&#x1EAD;n.</li></ul></li></ul><h2 id="b%C6%B0%E1%BB%9Bc-3-test-v%C3%A0-h%C6%B0%E1%BB%9Fng-th%E1%BB%A5-th%C3%A0nh-qu%E1%BA%A3">B&#x1B0;&#x1EDB;c 3: Test v&#xE0; h&#x1B0;&#x1EDF;ng th&#x1EE5; th&#xE0;nh qu&#x1EA3;</h2><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2024/03/result-send-mail-1.png?w=1024" class="kg-image" alt loading="lazy"></figure><p>C&#x1EA3;m &#x1A1;n b&#x1EA1;n, v&#xEC; &#x111;&#xE3; &#x111;&#x1ECD;c b&#xE0;i.</p><p>B&#xE0;i vi&#x1EBF;t c&#xF3; ngu&#x1ED3;n t&#x1EEB;: <a href="https://minhphong306.wordpress.com/2024/03/25/til-gui-mail-trong-php-bang-gmail/?ref=engineering.shopbase.com">Blog c&#x1EE7;a m&#xEC;nh</a>.</p>]]></content:encoded></item><item><title><![CDATA[Tìm hiểu về chuẩn JSON Merge Patch cùng Hằng béo]]></title><description><![CDATA[<p>-- Anh T&#xE8;o n&#xE0;y, d&#x1EA1;o n&#xE0;y em hay l&#xE0;m v&#x1EDB;i Fredrik, th&#x1EA5;y h&#x1EAF;n code s&#xE1;ng gh&#xEA;.</p><p>-- Code nh&#x1B0; n&#xE0;o m&#xE0; s&#xE1;ng?</p><p>-- <strong>README vi&</strong></p>]]></description><link>https://engineering.shopbase.com/tim-hieu-ve-chuan-json-merge-patch-cung-hang-beo/</link><guid isPermaLink="false">65d83e290b0ab5bbc6d70b75</guid><dc:creator><![CDATA[Phong Do]]></dc:creator><pubDate>Fri, 23 Feb 2024 06:47:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/image-5.png" medium="image"/><content:encoded><![CDATA[<img src="https://engineering.shopbase.com/content/images/2024/02/image-5.png" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o"><p>-- Anh T&#xE8;o n&#xE0;y, d&#x1EA1;o n&#xE0;y em hay l&#xE0;m v&#x1EDB;i Fredrik, th&#x1EA5;y h&#x1EAF;n code s&#xE1;ng gh&#xEA;.</p><p>-- Code nh&#x1B0; n&#xE0;o m&#xE0; s&#xE1;ng?</p><p>-- <strong>README vi&#x1EBF;t</strong> r&#x1EA5;t <strong>k&#x129;</strong>, code c&#xF3; <strong>design pattern r&#xF5; r&#xE0;ng,</strong> <strong>comment &#x111;&#x1EA7;y &#x111;&#x1EE7;</strong>. Ngo&#xE0;i ra c&#xF2;n <strong>&#x111;&#xFA;ng chu&#x1EA9;n</strong> n&#x1EEF;a.</p><p>-- Chu&#x1EA9;n? Chu&#x1EA9;n g&#xEC;?</p><p>-- V&#xED; d&#x1EE5; g&#x1EA7;n nh&#x1EA5;t l&#xE0; chu&#x1EA9;n <a href="https://www.rfc-editor.org/rfc/rfc7396?ref=engineering.shopbase.com">RFC7396: JSON Merge Patch</a></p><h2 id="t%C3%B3m-t%E1%BA%AFt-ki%E1%BA%BFn-th%E1%BB%A9c">T&#xF3;m t&#x1EAF;t ki&#x1EBF;n th&#x1EE9;c</h2><ul><li><strong>RFC 7396</strong> l&#xE0; m&#x1ED9;t ti&#xEA;u chu&#x1EA9;n c&#x1EE7;a <strong>IETF</strong> (Internet Engineering Task Force) &#x111;&#x1EB7;c bi&#x1EC7;t li&#xEA;n quan &#x111;&#x1EBF;n vi&#x1EC7;c <strong>thay &#x111;&#x1ED5;i c&#xE1;c t&#xE0;i nguy&#xEA;n JSON</strong> b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xE1;c t&#xE0;i li&#x1EC7;u <strong>JSON nh&#x1ECF;</strong> &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i l&#xE0; JSON Patch</li><li><strong>RFC = &quot;Request for Comments&quot;,</strong> c&#xF3; ngh&#x129;a l&#xE0; &quot;Y&#xEA;u c&#x1EA7;u &#xFD; ki&#x1EBF;n&quot; ho&#x1EB7;c &quot;&#x110;&#x1EC1; ngh&#x1ECB; &#xFD; ki&#x1EBF;n.&quot; C&#x1EE5; th&#x1EC3;, trong ng&#x1EEF; c&#x1EA3;nh c&#x1EE7;a IETF (Internet Engineering Task Force), RFC l&#xE0; m&#x1ED9;t lo&#x1EA1;t c&#xE1;c t&#xE0;i li&#x1EC7;u m&#xE0; nh&#x1EEF;ng ng&#x1B0;&#x1EDD;i tham gia &#x111;&#x1B0;a ra &#x111;&#x1EC3; m&#xF4; t&#x1EA3;, &#x111;&#x1EC1; xu&#x1EA5;t ho&#x1EB7;c &#x111;&#xE1;nh gi&#xE1; c&#xE1;c ti&#xEA;u chu&#x1EA9;n, giao th&#x1EE9;c, quy tr&#xEC;nh v&#xE0; c&#xE1;c v&#x1EA5;n &#x111;&#x1EC1; li&#xEA;n quan &#x111;&#x1EBF;n ph&#xE1;t tri&#x1EC3;n v&#xE0; qu&#x1EA3;n l&#xFD; Internet</li><li>B&#x1EA1;n hi&#x1EC3;u &#x111;&#x1A1;n gi&#x1EA3;n l&#xE0; quy &#x1B0;&#x1EDB;c &#x111;&#x1EC3; update JSON<ul><li>M&#x1EE5;c ti&#xEA;u sinh ra quy &#x1B0;&#x1EDB;c &#x111;&#x1EC3; c&#xF3; 1 c&#xE1;i chu&#x1EA9;n, c&#x1EA3; th&#x1EBF; gi&#x1EDB;i l&#xE0;m theo, tr&#xE1;nh m&#x1ED7;i &#xF4;ng m&#x1ED7;i ki&#x1EC3;u.</li></ul></li><li>RFC 7396 quy &#x1B0;&#x1EDB;c mu&#x1ED1;n c&#x1EAD;p nh&#x1EAD;t field n&#xE0;o th&#xEC; g&#x1EED;i field &#x111;&#xF3; l&#xEA;n th&#xF4;i, tr&#xE1;nh g&#x1EED;i to&#xE0;n b&#x1ED9; l&#xEA;n, t&#x1ED1;n b&#x103;ng th&#xF4;ng.</li><li>V&#x1EC1; c&#x1A1; b&#x1EA3;n th&#xEC; c&#xF3; c&#xE1;c nguy&#xEA;n t&#x1EAF;c sau:<ul><li>Ch&#x1EC9; g&#x1EED;i field n&#xE0;o c&#x1EA7;n update l&#xEA;n</li><li>N&#x1EBF;u field n&#xE0;o ch&#x1B0;a c&#xF3; trong object g&#x1ED1;c ~&gt; th&#xEA;m v&#xE0;o</li><li>N&#x1EBF;u field n&#xE0;o c&#xF3; trong object g&#x1ED1;c r&#x1ED3;i ~&gt; thay th&#x1EBF;</li><li>N&#x1EBF;u field n&#xE0;o m&#xE0; value l&#xE0; null ~&gt; x&#xF3;a field &#x111;i</li><li>Method l&#xE0; PATCH, Content-Type l&#xE0; <code>application/merge-patch+json</code></li></ul></li><li>Danh s&#xE1;ch &#x111;&#x1EA7;y &#x111;&#x1EE7; c&#xE1;c test cases:</li></ul><pre><code>ORIGINAL        PATCH            RESULT
   ------------------------------------------
   {&quot;a&quot;:&quot;b&quot;}       {&quot;a&quot;:&quot;c&quot;}       {&quot;a&quot;:&quot;c&quot;}

   {&quot;a&quot;:&quot;b&quot;}       {&quot;b&quot;:&quot;c&quot;}       {&quot;a&quot;:&quot;b&quot;,
                                    &quot;b&quot;:&quot;c&quot;}

   {&quot;a&quot;:&quot;b&quot;}       {&quot;a&quot;:null}      {}

   {&quot;a&quot;:&quot;b&quot;,       {&quot;a&quot;:null}      {&quot;b&quot;:&quot;c&quot;}
    &quot;b&quot;:&quot;c&quot;}

   {&quot;a&quot;:[&quot;b&quot;]}     {&quot;a&quot;:&quot;c&quot;}       {&quot;a&quot;:&quot;c&quot;}

   {&quot;a&quot;:&quot;c&quot;}       {&quot;a&quot;:[&quot;b&quot;]}     {&quot;a&quot;:[&quot;b&quot;]}

   {&quot;a&quot;: {         {&quot;a&quot;: {         {&quot;a&quot;: {
     &quot;b&quot;: &quot;c&quot;}       &quot;b&quot;: &quot;d&quot;,       &quot;b&quot;: &quot;d&quot;
   }                 &quot;c&quot;: null}      }
                   }               }

   {&quot;a&quot;: [         {&quot;a&quot;: [1]}      {&quot;a&quot;: [1]}
     {&quot;b&quot;:&quot;c&quot;}
    ]
   }

   [&quot;a&quot;,&quot;b&quot;]       [&quot;c&quot;,&quot;d&quot;]       [&quot;c&quot;,&quot;d&quot;]

   {&quot;a&quot;:&quot;b&quot;}       [&quot;c&quot;]           [&quot;c&quot;]

   {&quot;a&quot;:&quot;foo&quot;}     null            null

   {&quot;a&quot;:&quot;foo&quot;}     &quot;bar&quot;           &quot;bar&quot;

   {&quot;e&quot;:null}      {&quot;a&quot;:1}         {&quot;e&quot;:null,
                                    &quot;a&quot;:1}

   [1,2]           {&quot;a&quot;:&quot;b&quot;,       {&quot;a&quot;:&quot;b&quot;}
                    &quot;c&quot;:null}

   {}              {&quot;a&quot;:            {&quot;a&quot;:
                    {&quot;bb&quot;:           {&quot;bb&quot;:
                     {&quot;ccc&quot;:          {}}}
                      null}}}</code></pre><h2 id="ch%C3%A9m">Ch&#xE9;m</h2><p>-- Anh c&#x169;ng ch&#x1B0;a nghe t&#x1EDB;i c&#xE1;i chu&#x1EA9;n n&#xE0;y bao gi&#x1EDD;. Nghe nguy hi&#x1EC3;m nh&#x1EC9;. M&#xE0;y t&#xF3;m t&#x1EAF;t trong m&#x1B0;&#x1EDD;i l&#x103;m ch&#x1EEF; &#x111;i xem c&#xF3; g&#xEC; hot n&#xE0;o?</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/big_smile.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- V&#x1EC1; c&#x1A1; b&#x1EA3;n, n&#xF3; l&#xE0; chu&#x1EA9;n &#x111;&#x1EC3; anh update JSON.</p><p>-- Update JSON? B&#xEC;nh th&#x1B0;&#x1EDD;ng anh th&#x1EA5;y &#x111;&#x1ED9;i dev g&#x1EED;i c&#x1EA3; c&#x1EE5;c l&#xEA;n, replace l&#xE0; xong m&#xE0;?</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/brick.jpg?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- &#x110;&#xFA;ng l&#xE0; v&#x1EAD;y. Tuy nhi&#xEA;n vi&#x1EC7;c g&#x1EED;i to&#xE0;n b&#x1ED9; JSON l&#xEA;n s&#x1EBD; l&#xE0;m t&#x1ED1;n b&#x103;ng th&#xF4;ng. JSON b&#xE9; kh&#xF4;ng sao, JSON to t&#x1ED1;n c&#x1EA3; Kb ch&#x1EE9; ch&#x1EB3;ng ch&#x1A1;i. M&#x1ED9;t ng&#xE0;y v&#xE0;i tri&#x1EC7;u t&#x1EDB;i v&#xE0;i tr&#x103;m tri&#x1EC7;u request, anh c&#xF3; bi&#x1EBF;t n&#xF3; nhi&#x1EC1;u th&#x1EBF; n&#xE0;o kh&#xF4;ng?</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/sad.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- &#x1EEA; nh&#x1EC9;. Nghe m&#xE0;y n&#xF3;i, anh th&#x1EA5;y n&#xF3; c&#x169;ng... to to. Th&#x1EBF; n&#xF3;i r&#xF5; h&#x1A1;n v&#x1EC1; chu&#x1EA9;n &#x111;i.</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/oh.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- Chu&#x1EA9;n JSON Merge Patch, hay c&#xF2;n g&#x1ECD;i l&#xE0; RFC 7396, quy &#x1B0;&#x1EDB;c m&#x1ED9;t s&#x1ED1; nguy&#xEA;n t&#x1EAF;c sau khi update JSON value</p><ul><li>Ch&#x1EC9; g&#x1EED;i field n&#xE0;o c&#x1EA7;n update l&#xEA;n</li><li>N&#x1EBF;u field n&#xE0;o ch&#x1B0;a c&#xF3; trong object g&#x1ED1;c ~&gt; th&#xEA;m v&#xE0;o</li><li>N&#x1EBF;u field n&#xE0;o c&#xF3; trong object g&#x1ED1;c r&#x1ED3;i ~&gt; thay th&#x1EBF;</li><li>N&#x1EBF;u field n&#xE0;o m&#xE0; value l&#xE0; null ~&gt; x&#xF3;a field &#x111;i</li><li>Method l&#xE0; PATCH</li></ul><p>-- Nghe h&#x1A1;i l&#xED; thuy&#x1EBF;t. Anh ngh&#x129; n&#xEA;n c&#xF3; v&#xE0;i v&#xED; d&#x1EE5;?</p><p>-- V&#xED; d&#x1EE5; th&#x1EBF; n&#xE0;y: gi&#x1EA3; s&#x1EED; ban &#x111;&#x1EA7;u, file JSON c&#x1EE7;a em tr&#xF4;ng nh&#x1B0; sau:</p><pre><code>{
     &quot;title&quot;: &quot;From Hang xinh gai with love&quot;,
     &quot;author&quot; : {
       &quot;givenName&quot; : &quot;Hang&quot;,
       &quot;familyName&quot; : &quot;Xinh Gai&quot;
     },
     &quot;tags&quot;:[ &quot;girl_pho&quot;, &quot;girl_thu_do&quot; ],
     &quot;content&quot;: &quot;A girl, who love Go programming&quot;
   }</code></pre><p>Gi&#x1EA3; s&#x1EED; em mu&#x1ED1;n x&#xF3;a <code>familyName</code> &#x111;i, thay <code>content</code> th&#xE0;nh: &quot;Hang xinh gai sieu cap vjp pr0&quot; th&#xEC; em s&#x1EBD; g&#x1EED;i patch request v&#x1EDB;i n&#x1ED9;i dung nh&#x1B0; sau:</p><pre><code>PATCH /my/resource HTTP/1.1
   Host: example.org
   Content-Type: application/merge-patch+json
 
   {
     &quot;author&quot;: {
       &quot;familyName&quot;: null
     },
     &quot;content&quot;: &quot;Hang xinh gai sieu cap vjp pr0&quot;
   }</code></pre><p>V&#xE0; k&#x1EBF;t qu&#x1EA3; nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c cu&#x1ED1;i c&#xF9;ng l&#xE0;:</p><pre><code>{
     &quot;title&quot;: &quot;From Hang xinh gai with love&quot;,
     &quot;author&quot; : {
       &quot;givenName&quot; : &quot;Hang&quot;
     },
     &quot;tags&quot;:[ &quot;girl_pho&quot;, &quot;girl_thu_do&quot; ],
     &quot;content&quot;: &quot;Hang xinh gai sieu cap vjp pr0&quot;
   }</code></pre><p>-- Nghe c&#x169;ng &#x111;&#x1A1;n gi&#x1EA3;n vl nh&#x1EC9;?</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/sweet_kiss.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- &#x110;&#x1A1;n gi&#x1EA3;n m&#xE0;. Th&#x1EBF; v&#xED; d&#x1EE5; em mu&#x1ED1;n thay &#x111;&#x1ED5;i tags th&#xE0;nh &quot;girl_ngoan_hien&quot; v&#xE0; &quot;1235_anh_co_danh_roi_nhip_nao_khong&quot; th&#xEC; l&#xE0;m th&#x1EBF; n&#xE0;o?</p><p>-- Anh ngh&#x129; ch&#x1EC9; c&#x1EA7;n g&#x1EED;i body l&#xEA;n v&#x1EDB;i gi&#xE1; tr&#x1ECB; tag m&#x1EDB;i l&#xE0; xong?</p><pre><code>PATCH /my/resource HTTP/1.1
   Host: example.org
   Content-Type: application/merge-patch+json
 
   {
     &quot;tags&quot;:[ &quot;girl_ngoan_hien&quot;, &quot;1235_anh_co_danh_roi_nhip_nao_khong&quot; ]
   }</code></pre><p>-- That&apos;s right. Th&#x1EBF; &#x111;&#x1ED1; anh, v&#xED; d&#x1EE5; n&#xE0;y th&#xEC; s&#x1EBD; nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c g&#xEC;?&#x2002;</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/sweet_kiss.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>JSON g&#x1ED1;c</p><pre><code>{&quot;a&quot;:&quot;foo&quot;}</code></pre><p>Request body</p><pre><code>PATCH /my/resource HTTP/1.1
   Host: example.org
   Content-Type: application/merge-patch+json

 null</code></pre><p>-- &#xC1;m&#x1EE5;&#x110;, qu&#x1EA3; null kh&#xF3; th&#x1EBF;</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/oh.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>. Anh &#x111;o&#xE1;n l&#xE0; k&#x1EBF;t qu&#x1EA3; gi&#x1EEF; nguy&#xEA;n <code>{&quot;a&quot;:&quot;foo&quot;}</code></p><p>-- Sai. K&#x1EBF;t qu&#x1EA3; s&#x1EBD; v&#x1EC1; <code>null</code> nh&#xE9;.</p><p>-- C&#xF2;n nhi&#x1EC1;u case &#x111;&#x1EB7;c bi&#x1EC7;t kh&#xF4;ng? M&#xE0;y n&#xF3;i n&#x1ED1;t cho anh bi&#x1EBF;t n&#xE0;o?</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/sad.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- &#x110;&#x1EA7;y &#x111;&#x1EE7; c&#xE1;c case th&#xEC; anh xem b&#x1EA3;ng sau</p><pre><code>ORIGINAL        PATCH            RESULT
   &#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;&#x2014;
   {&quot;a&quot;:&quot;b&quot;}       {&quot;a&quot;:&quot;c&quot;}       {&quot;a&quot;:&quot;c&quot;}

   {&quot;a&quot;:&quot;b&quot;}       {&quot;b&quot;:&quot;c&quot;}       {&quot;a&quot;:&quot;b&quot;,
                                    &quot;b&quot;:&quot;c&quot;}

   {&quot;a&quot;:&quot;b&quot;}       {&quot;a&quot;:null}      {}

   {&quot;a&quot;:&quot;b&quot;,       {&quot;a&quot;:null}      {&quot;b&quot;:&quot;c&quot;}
    &quot;b&quot;:&quot;c&quot;}

   {&quot;a&quot;:[&quot;b&quot;]}     {&quot;a&quot;:&quot;c&quot;}       {&quot;a&quot;:&quot;c&quot;}

   {&quot;a&quot;:&quot;c&quot;}       {&quot;a&quot;:[&quot;b&quot;]}     {&quot;a&quot;:[&quot;b&quot;]}

   {&quot;a&quot;: {         {&quot;a&quot;: {         {&quot;a&quot;: {
     &quot;b&quot;: &quot;c&quot;}       &quot;b&quot;: &quot;d&quot;,       &quot;b&quot;: &quot;d&quot;
   }                 &quot;c&quot;: null}      }
                   }               }

   {&quot;a&quot;: [         {&quot;a&quot;: [1]}      {&quot;a&quot;: [1]}
     {&quot;b&quot;:&quot;c&quot;}
    ]
   }

   [&quot;a&quot;,&quot;b&quot;]       [&quot;c&quot;,&quot;d&quot;]       [&quot;c&quot;,&quot;d&quot;]

   {&quot;a&quot;:&quot;b&quot;}       [&quot;c&quot;]           [&quot;c&quot;]

   {&quot;a&quot;:&quot;foo&quot;}     null            null

   {&quot;a&quot;:&quot;foo&quot;}     &quot;bar&quot;           &quot;bar&quot;

   {&quot;e&quot;:null}      {&quot;a&quot;:1}         {&quot;e&quot;:null,
                                    &quot;a&quot;:1}

   [1,2]           {&quot;a&quot;:&quot;b&quot;,       {&quot;a&quot;:&quot;b&quot;}
                    &quot;c&quot;:null}

   {}              {&quot;a&quot;:            {&quot;a&quot;:
                    {&quot;bb&quot;:           {&quot;bb&quot;:
                     {&quot;ccc&quot;:          {}}}
                      null}}}</code></pre><p>-- Anh c&#xF3; th&#x1EAF;c m&#x1EAF;c g&#xEC; n&#x1EEF;a kh&#xF4;ng? Em k&#x1EBF;t b&#xE0;i &#x111;&#xE2;y?</p><p>-- Hm... Anh &#x111;ang ngh&#x129; l&#xE0; m&#xEC;nh c&#xF3; th&#x1EC3; t&#x1EF1; s&#xE1;ng t&#x1EA1;o quy &#x1B0;&#x1EDB;c ra r&#x1ED3;i code theo quy &#x1B0;&#x1EDB;c &#x111;&#x1EA5;y l&#xE0; &#x111;&#x1B0;&#x1EE3;c nh&#x1EC9;? &#x110;&#x1EE1; ph&#x1EA3;i h&#x1ECD;c nhi&#x1EC1;u chu&#x1EA9;n. H&#x1A1;i...m&#x1EC7;t.</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/sweet_kiss.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- L&#xE0;m nh&#x1B0; anh m&#x1EDB;i l&#xE0; m&#x1EC7;t. Anh &#x111;&#x1EBB; ra m&#x1ED9;t chu&#x1EA9;n m&#xE0; kh&#xF4;ng c&#xF3; nhi&#x1EC1;u ng&#x1B0;&#x1EDD;i ki&#x1EC3;m duy&#x1EC7;t ~&gt; r&#x1EA5;t d&#x1EC5; sai. Ch&#x1B0;a k&#x1EC3; anh tuy&#x1EC3;n ng&#x1B0;&#x1EDD;i m&#x1EDB;i v&#xE0;o, h&#x1ECD; l&#x1EA1;i ph&#x1EA3;i &#x111;&#x1ECD;c c&#xE1;i chu&#x1EA9;n c&#x1EE7;a anh, l&#xE0;m learning curve t&#x103;ng.</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/brick.jpg?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>-- &#x1EEA; nh&#x1EC9;. Th&#x1EBF; &#x111;&#x1EB9;p nh&#x1EA5;t v&#x1EAB;n l&#xE0; l&#x1EA5;y chu&#x1EA9;n qu&#x1ED1;c t&#x1EBF; m&#xE0; l&#xE0;m.</p><p>-- Ch&#x1EE9; c&#xF2;n g&#xEC; n&#x1EEF;a..</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/beauty.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><hr><p>C&#x1EA3;m &#x1A1;n b&#x1EA1;n, v&#xEC; &#x111;&#xE3; &#x111;&#x1ECD;c b&#xE0;i.</p><p>Tranh th&#x1EE7; &#x111;&#x1EA7;u xu&#xE2;n, trong l&#xFA;c &#x111;&#x1ECD;c code c&#x1EE7;a m&#x1ED9;t b&#x1EA1;n &#x111;&#x1ED3;ng nghi&#x1EC7;p th&#xEC; m&#xEC;nh n&#x1EA3;y ra &#xFD; t&#x1B0;&#x1EDF;ng vi&#x1EBF;t b&#xE0;i ~&gt; v&#xE0;o vi&#x1EC7;c lu&#xF4;n</p><figure class="kg-card kg-image-card"><img src="https://minhphong306.files.wordpress.com/2020/03/big_smile.png?w=56" class="kg-image" alt="T&#xEC;m hi&#x1EC3;u v&#x1EC1; chu&#x1EA9;n JSON Merge Patch c&#xF9;ng H&#x1EB1;ng b&#xE9;o" loading="lazy"></figure><p>Ch&#xFA;c b&#x1EA1;n v&#xE0; gia &#x111;&#xEC;nh m&#x1ED9;t n&#x103;m m&#x1EDB;i th&#x1EAD;t nhi&#x1EC1;u s&#x1EE9;c kh&#x1ECF;e, &#x111;&#x1EA1;t &#x111;&#x1B0;&#x1EE3;c c&#xE1;c m&#x1EE5;c ti&#xEA;u &#x111;&#x1EB7;t ra trong 2024 nha ^^</p><hr><p> B&#xE0;i vi&#x1EBF;t &#x111;&#x1B0;&#x1EE3;c l&#x1EA5;y t&#x1EEB; ngu&#x1ED3;n: <a href="https://minhphong306.wordpress.com/2024/02/12/tim-hieu-ve-chuan-json-merge-patch-cung-hang-beo/?ref=engineering.shopbase.com#more-4215" rel="noreferrer">Blog c&#x1EE7;a m&#xEC;nh</a></p>]]></content:encoded></item><item><title><![CDATA[Amazon EKS authenticate by Google accounts]]></title><description><![CDATA[<h1 id="gi%E1%BB%9Bi-thi%E1%BB%87u">Gi&#x1EDB;i thi&#x1EC7;u</h1>
<p>Kubernetes (k8s) l&#xE0; m&#x1ED9;t h&#x1EC7; th&#x1ED1;ng m&#xE3; ngu&#x1ED3;n m&#x1EDF; gi&#xFA;p qu&#x1EA3;n l&#xFD; v&#xE0; tri&#x1EC3;n khai c&#xE1;c containerized applications tr&#xEA;n m&#xF4;i</p>]]></description><link>https://engineering.shopbase.com/amazon-eks-authenticate-by-google-accounts/</link><guid isPermaLink="false">65bb0dca95b8649d9ab036b7</guid><category><![CDATA[eks]]></category><category><![CDATA[aws]]></category><dc:creator><![CDATA[Nam Nguyen]]></dc:creator><pubDate>Fri, 02 Feb 2024 04:16:19 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/EKS.jpeg" medium="image"/><content:encoded><![CDATA[<h1 id="gi%E1%BB%9Bi-thi%E1%BB%87u">Gi&#x1EDB;i thi&#x1EC7;u</h1>
<img src="https://engineering.shopbase.com/content/images/2024/02/EKS.jpeg" alt="Amazon EKS authenticate by Google accounts"><p>Kubernetes (k8s) l&#xE0; m&#x1ED9;t h&#x1EC7; th&#x1ED1;ng m&#xE3; ngu&#x1ED3;n m&#x1EDF; gi&#xFA;p qu&#x1EA3;n l&#xFD; v&#xE0; tri&#x1EC3;n khai c&#xE1;c containerized applications tr&#xEA;n m&#xF4;i tr&#x1B0;&#x1EDD;ng ph&#xE2;n t&#xE1;n ph&#x1ED5; bi&#x1EBF;n nh&#x1EA5;t hi&#x1EC7;n nay. AWS hi&#x1EC7;n &#x111;ang h&#x1ED7; tr&#x1EE3; ng&#x1B0;&#x1EDD;i d&#xF9;ng qu&#x1EA3;n l&#xFD; h&#x1EC7; th&#x1ED1;ng Kubernetes d&#x1B0;&#x1EDB;i d&#x1EA1;ng m&#x1ED9;t d&#x1ECB;ch c&#xF3; t&#xEA;n l&#xE0; Elastic Kubernetes Service - EKS.</p>
<p>B&#xE0;i vi&#x1EBF;t n&#xE0;y s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;ch x&#xE1;c th&#x1EF1;c v&#x1EDB;i EKS th&#xF4;ng qua Google Accounts, mang l&#x1EA1;i t&#xED;nh linh ho&#x1EA1;t trong vi&#x1EC7;c qu&#x1EA3;n l&#xFD; c&#x1EE5;m EKS.</p>
<p>*<em>Ch&#xFA; &#xFD;: B&#xE0;i vi&#x1EBF;t n&#xE0;y t&#x1EAD;p trung v&#xE0;o vi&#x1EC7;c h&#x1B0;&#x1EDB;ng d&#x1EAB;n ng&#x1B0;&#x1EDD;i d&#xF9;ng tri&#x1EC3;n khai x&#xE1;c th&#x1EF1;c tr&#xEA;n EKS th&#xF4;ng qua Google Accounts v&#xE0; gi&#x1EA3; &#x111;&#x1ECB;nh r&#x1EB1;ng m&#x1ECD;i ng&#x1B0;&#x1EDD;i &#x111;&#x1EC1;u &#x111;&#xE3; l&#xE0;m vi&#x1EC7;c v&#x1EDB;i EKS v&#xE0; Google Accounts r&#x1ED3;i.</em></p>
<h1 id="%C4%91%E1%BA%B7t-v%E1%BA%A5n-%C4%91%E1%BB%81">&#x110;&#x1EB7;t v&#x1EA5;n &#x111;&#x1EC1;</h1>
<p>&#x110;&#x1ED1;i v&#x1EDB;i c&#xE1;c doanh nghi&#x1EC7;p hay c&#xE1; nh&#xE2;n &#x111;ang v&#x1EAD;n h&#xE0;nh h&#x1EC7; th&#x1ED1;ng tr&#xEA;n c&#xE1;c c&#x1EE5;m EKS, vi&#x1EC7;c qu&#x1EA3;n l&#xFD; c&#x1EE5;m y&#xEA;u c&#x1EA7;u ng&#x1B0;&#x1EDD;i d&#xF9;ng ph&#x1EA3;i x&#xE1;c th&#x1EF1;c th&#xF4;ng qua <code>AWS</code>, v&#x1EC1; c&#x1A1; b&#x1EA3;n qu&#x1EA3;n tr&#x1ECB; vi&#xEA;n, ng&#x1B0;&#x1EDD;i d&#xF9;ng h&#x1EC7; th&#x1ED1;ng (c&#x1EE5;m) EKS &#x111;&#x1EC1;u ph&#x1EA3;i c&#xF3; t&#xE0;i kho&#x1EA3;n tr&#xEA;n AWS khi mu&#x1ED1;n t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i c&#x1EE5;m. Trong khi &#x111;&#xF3; vi&#x1EC7;c qu&#x1EA3;n l&#xFD; t&#xE0;i kho&#x1EA3;n nh&#xE2;n vi&#xEA;n trong doanh nghi&#x1EC7;p s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c qu&#x1EA3;n l&#xFD; th&#xF4;ng qua c&#xE1;c b&#xEA;n/d&#x1ECB;ch v&#x1EE5; kh&#xE1;c nh&#x1B0; Google (th&#xF4;ng qua Gsuite ch&#x1EB3;ng h&#x1EA1;n). N&#xEA;n n&#x1EBF;u t&#xED;ch h&#x1EE3;p &#x111;&#x1B0;&#x1EE3;c kh&#xE2;u x&#xE1;c th&#x1EF1;c c&#x1EE7;a EKS v&#x1EDB;i c&#xE1;c c&#xF4;ng c&#x1EE5; qu&#x1EA3;n l&#xFD; t&#xE0;i kho&#x1EA3;n chung th&#xEC; s&#x1EBD; gi&#xFA;p &#xED;ch r&#x1EA5;t nhi&#x1EC1;u cho doanh nghi&#x1EC7;p.</p>
<h1 id="h%C6%B0%E1%BB%9Bng-gi%E1%BA%A3i-quy%E1%BA%BFt">H&#x1B0;&#x1EDB;ng gi&#x1EA3;i quy&#x1EBF;t</h1>
<p>Th&#x1EAD;t may, EKS (Kubernetes) c&#xF3; h&#x1ED7; tr&#x1EE3; m&#x1ED9;t giao th&#x1EE9;c x&#xE1;c th&#x1EF1;c c&#xF3; t&#xEA;n l&#xE0; Open ID Connect (OIDC) v&#xE0; Google c&#x169;ng &#x111;ang h&#x1ED7; tr&#x1EE3; v&#xE0; tri&#x1EC3;n khai giao th&#x1EE9;c n&#xE0;y. T&#x1EEB; &#x111;&#xE2;y m&#x1EDF; ra con &#x111;&#x1B0;&#x1EDD;ng &#x111;&#x1EC3; c&#xF3; th&#x1EC3; tri&#x1EC3;n khai vi&#x1EC7;c qu&#x1EA3;n l&#xFD; c&#x1EE5;m EKS th&#xF4;ng qua Google Accounts.</p>
<h1 id="oidc-l%C3%A0-g%C3%AC">OIDC l&#xE0; g&#xEC;</h1>
<p>&#x110;&#x1EA7;u ti&#xEA;n ch&#xFA;ng ta c&#xF9;ng t&#xEC;m hi&#x1EC3;u s&#x1A1; qua v&#x1EC1; OIDC, v&#x1EAD;y OIDC l&#xE0; g&#xEC;?</p>
<blockquote>
<p>OIDC l&#xE0; vi&#x1EBF;t t&#x1EAF;t c&#x1EE7;a &quot;OpenID Connect&quot; m&#x1ED9;t giao th&#x1EE9;c x&#xE1;c th&#x1EF1;c &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng tr&#xEA;n OAuth 2.0. OIDC cung c&#x1EA5;p m&#x1ED9;t c&#xE1;ch ti&#xEA;u chu&#x1EA9;n &#x111;&#x1EC3; x&#xE1;c th&#x1EF1;c v&#xE0; qu&#x1EA3;n l&#xFD; danh t&#xED;nh ng&#x1B0;&#x1EDD;i d&#xF9;ng tr&#xEA;n internet. Giao th&#x1EE9;c n&#xE0;y ch&#x1EE7; y&#x1EBF;u &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng trong vi&#x1EC7;c x&#xE1;c th&#x1EF1;c ng&#x1B0;&#x1EDD;i d&#xF9;ng khi h&#x1ECD; truy c&#x1EAD;p c&#xE1;c &#x1EE9;ng d&#x1EE5;ng web, &#x1EE9;ng d&#x1EE5;ng di &#x111;&#x1ED9;ng v&#xE0; c&#xE1;c d&#x1ECB;ch v&#x1EE5; tr&#x1EF1;c tuy&#x1EBF;n kh&#xE1;c.</p>
</blockquote>
<h1 id="chu%E1%BA%A9n-b%E1%BB%8B-m%C3%B4i-tr%C6%B0%E1%BB%9Dng">Chu&#x1EA9;n b&#x1ECB; m&#xF4;i tr&#x1B0;&#x1EDD;ng</h1>
<ul>
<li>&#x110;&#xE3; tri&#x1EC3;n khai EKS cluster tr&#xEA;n t&#xE0;i kho&#x1EA3;ng AWS</li>
<li>C&#xF3; account Google v&#xE0; c&#xF3; th&#x1EC3; v&#xE0;o &#x111;&#x1B0;&#x1EE3;c trang qu&#x1EA3;n l&#xFD; (<a href="https://console.cloud.google.com/?ref=engineering.shopbase.com">console</a>)</li>
<li>&#x110;&#xE3; c&#xE0;i &#x111;&#x1EB7;t c&#xE1;c c&#xF4;ng c&#x1EE5; eksctl, kubectl</li>
</ul>
<p>Ph&#xED;a tr&#xEA;n l&#xE0; nh&#x1EEF;ng c&#xF4;ng c&#x1EE5; c&#x1EA7;n thi&#x1EBF;t &#x111;&#x1EC3; h&#x1ED7; tr&#x1EE3; vi&#x1EC7;c tri&#x1EC3;n khai x&#xE1;c th&#x1EF1;c v&#x1EDB;i EKS th&#xF4;ng qua Google Accounts, c&#xF2;n b&#xE2;y gi&#x1EDD; ch&#xFA;ng ta s&#x1EBD; &#x111;i v&#xE0;o qu&#xE1; tr&#xEC;nh c&#x1EA5;u h&#xEC;nh cho t&#x1EEB;ng th&#xE0;nh ph&#x1EA7;n.</p>
<h1 id="c%E1%BA%A5u-h%C3%ACnh-cho-google">C&#x1EA5;u h&#xEC;nh cho Google</h1>
<p>&#x110;&#x1EC3; c&#xF3; th&#x1EC3; t&#xED;ch h&#x1EE3;p vi&#x1EC7;c x&#xE1;c th&#x1EF1;c c&#x1EE7;a Google v&#xE0;o c&#x1EE5;m EKS, ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i t&#x1EA1;o m&#x1ED9;t Credentials cho OAuth trong Google, ph&#xED;a d&#x1B0;&#x1EDB;i l&#xE0; c&#xE1;c b&#x1B0;&#x1EDB;c c&#x1EA7;n th&#x1EF1;c hi&#x1EC7;n &#x111;&#x1EC3; t&#x1EA1;o &#x1EE9;ng d&#x1EE5;ng:</p>
<ol>
<li>V&#xE0;o console google <a href="https://console.cloud.google.com/?ref=engineering.shopbase.com">https://console.cloud.google.com/</a></li>
<li>T&#x1EA1;o project th&#xF4;ng qua New Project
<ul>
<li>Project Name: T&#xEA;n c&#x1EE7;a project</li>
</ul>
</li>
<li>V&#xE0;o tab <code>Oauth Consent Screen</code>
<ul>
<li>&#x110;i&#x1EC1;n th&#xF4;ng tin v&#x1EC1; application v&#xE0; email c&#x1EE7;a developer</li>
<li>Th&#xEA;m scope v&#xE0;o consent screen
<ul>
<li>Scope c&#x1EA7;n c&#xF3;:
<ul>
<li>email</li>
<li>profile</li>
<li>openid</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>V&#xE0;o tab Credentials
<ul>
<li>Ch&#x1ECD;n Create Credentials</li>
<li>Ch&#x1ECD;n Oauth Client ID</li>
<li>Ch&#x1ECD;n Web Application
<ul>
<li>Nh&#x1EAD;p t&#xEA;n &#x1EE9;ng d&#x1EE5;ng</li>
<li>Th&#xEA;m URI <a href="http://localhost:8000/?ref=engineering.shopbase.com"><code>http://localhost:8000</code></a> t&#x1EA1;i <strong>Authorized redirect URIs</strong></li>
</ul>
</li>
<li>Ch&#x1ECD;n t&#x1EA1;o &#x1EE9;ng d&#x1EE5;ng</li>
</ul>
</li>
<li>L&#x1EA5;y Oauth client bao g&#x1ED3;m:
<ol>
<li>Client ID</li>
<li>Client secret</li>
</ol>
</li>
</ol>
<h1 id="c%E1%BA%A5u-h%C3%ACnh-cho-eks">C&#x1EA5;u h&#xEC;nh cho EKS</h1>
<p>*<em>B&#xE0;i vi&#x1EBF;t n&#xE0;y s&#x1EBD; kh&#xF4;ng &#x111;i qua vi&#x1EC7;c h&#x1B0;&#x1EDB;ng d&#x1EAB;n t&#x1EA1;o c&#x1EE5;m EKS, tuy nhi&#xEA;n b&#x1EA1;n c&#xF3; th&#x1EC3; d&#x1EC5; d&#xE0;ng t&#x1EA1;o cho m&#xEC;nh m&#x1ED9;t cluster EKS th&#xF4;ng qua console ho&#x1EB7;c <a href="https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html?ref=engineering.shopbase.com">eksctl</a>.</em></p>
<p>&#x110;&#x1ED1;i v&#x1EDB;i EKS, ch&#xFA;ng ta c&#x1EA7;n ph&#x1EA3;i c&#x1EA5;u h&#xEC;nh li&#xEA;n k&#x1EBF;t <strong>OIDC identity providers</strong> (&#x1EDF; &#x111;&#xE2;y l&#xE0; Google) v&#xE0;o c&#x1EE5;m EKS, &#x111;&#x1EC3; cho c&#x1EE5;m EKS bi&#x1EBF;t r&#x1EB1;ng c&#xF3; th&#x1EC3; tin t&#x1B0;&#x1EDF;ng th&#x1EF1;c hi&#x1EC7;n c&#xE1;c ph&#x1B0;&#x1A1;ng ph&#xE1;p trao &#x111;&#x1ED5;i th&#xF4;ng tin v&#x1EC1; danh t&#xED;nh ng&#x1B0;&#x1EDD;i d&#xF9;ng tr&#xEA;n c&#x1EE5;m.</p>
<h2 id="th%C3%B4ng-qua-aws-management-console">Th&#xF4;ng qua AWS Management Console</h2>
<ol>
<li>V&#xE0;o trang qu&#x1EA3;n l&#xFD; EKS t&#x1EA1;i <a href="https://console.aws.amazon.com/eks/home?ref=engineering.shopbase.com#/clusters">https://console.aws.amazon.com/eks/home#/clusters</a></li>
<li>Ch&#x1ECD;n cluster c&#x1EE7;a b&#x1EA1;n</li>
<li>Ch&#x1ECD;n tab <strong>Configuration</strong>, v&#xE0; ch&#x1ECD;n tab <strong>Authentication</strong></li>
<li>Trong trang <strong>OIDC Identity Providers, ch&#x1ECD;n Associate Identity Provider</strong></li>
<li>T&#x1EA1;i trang <strong>Associate OIDC Identity Provider, nh&#x1EAD;p v&#xE0; ch&#x1ECD;n theo c&#xE1;c l&#x1EF1;a ch&#x1ECD;n sau:</strong>
<ul>
<li>Name: nh&#x1EAD;p unique name c&#x1EE7;a OIDC provider</li>
<li>Issue URL: nh&#x1EAD;p URL c&#x1EE7;a provider, URL n&#xE0;y c&#x1EA7;n ph&#x1EA3;i v&#xE0;o &#x111;&#x1B0;&#x1EE3;c th&#xF4;ng qua internet</li>
<li>Client ID: nh&#x1EAD;p OIDC identity provider&apos;s client ID (c&#xF2;n g&#x1ECD;i l&#xE0; <strong>audience)</strong></li>
<li>Username claim: nh&#x1EAD;p claim &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng &#x111;&#x1EC3; l&#xE0;m username</li>
<li>Group claim: nh&#x1EAD;p claim &#x111;&#x1B0;&#x1EE3;c d&#xF9;ng &#x111;&#x1EC3; l&#xE0;m group</li>
<li>(Optional) Ch&#x1ECD;n <strong>Advanced options</strong>, nh&#x1EAD;p ho&#x1EB7;c ch&#x1ECD;n c&#xE1;c th&#xF4;ng tin sau:
<ul>
<li><strong>Username prefix:</strong> nh&#x1EAD;p m&#x1ED9;t chu&#x1ED7;i, chu&#x1ED7;i n&#xE0;y &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; th&#xEA;m v&#xE0;o &#x111;&#x1EA7;u username claims &#x1EDF; ph&#xED;a tr&#xEA;n &#x111;&#x1EC3; tr&#xE1;nh vi&#x1EC7;c tr&#xF9;ng l&#x1EB7;p gi&#x1EEF;a c&#xE1;c username &#x111;&#xE3; t&#x1ED3;n t&#x1EA1;i. N&#x1EBF;u kh&#xF4;ng cung c&#x1EA5;p value n&#xE0;y v&#xE0; username kh&#xF4;ng ph&#x1EA3;i email th&#xEC; m&#x1EB7;c &#x111;&#x1ECB;nh prefix s&#x1EBD; l&#xE0; Issuer URL. B&#x1EA1;n c&#x169;ng c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng gi&#xE1; tr&#x1ECB;  <code>-</code> &#x111;&#x1EC3; t&#x1EAF;t t&#xED;nh n&#x103;ng prefix n&#xE0;y. V&#xE0; kh&#xF4;ng &#x111;&#x1B0;&#x1EE3;c ch&#x1EC9; &#x111;&#x1ECB;nh <code>system:</code> hay b&#x1EA5;t k&#x1EF3; chu&#x1ED7;i n&#xE0;o &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o t&#x1EEB; n&#xF3; &#x111;&#x1EC3; l&#xE0;m username prefix</li>
<li>Group prefix: Nh&#x1EAD;p m&#x1ED9;t chu&#x1ED7;i, chu&#x1ED7;i n&#xE0;y &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; th&#xEA;m v&#xE0;o &#x111;&#x1EA7;u group claims &#x1EDF; ph&#xED;a tr&#xEA;n.</li>
<li><strong>Required claims: ch&#x1ECD;n th&#xEA;m nh&#x1EEF;ng claims c&#x1EA7;n &#x111;&#x1B0;&#x1EE3;c l&#x1EA5;y ra t&#x1EEB; id token</strong></li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="th%C3%B4ng-qua-eksctl">Th&#xF4;ng qua eksctl</h2>
<ol>
<li>
<p>T&#x1EA1;o file c&#xF3; t&#xEA;n l&#xE0; <code>associate-identity-provider.yaml</code> v&#x1EDB;i n&#x1ED9;i dung sau. Replace c&#xE1;c <code>*example value*</code> v&#x1EDB;i gi&#xE1; tr&#x1ECB; c&#x1EE7;a b&#x1EA1;n</p>
<pre><code class="language-yaml">---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: *my-cluster*
  region: *your-region-code*

identityProviders:
  - name: *my-provider*
    type: oidc
    issuerUrl: *https://example.com*
    clientId: *kubernetes*
    usernameClaim: *email*
    usernamePrefix: oidc:
    groupsClaim: *my-claim*
    groupsPrefix: oidc:
    requiredClaims:
      string: *string*
    tags:
      env: *dev*
</code></pre>
</li>
<li>
<p>T&#x1EA1;o provider:</p>
<pre><code class="language-bash">eksctl associate identityprovider -f associate-identity-provider.yaml
</code></pre>
</li>
</ol>
<p>Sau khi th&#x1EF1;c hi&#x1EC7;n c&#xE1;c b&#x1B0;&#x1EDB;c tr&#xEA;n, EKS &#x111;&#xE3; c&#xF3; th&#x1EC3; li&#xEA;n k&#x1EBF;t v&#x1EDB;i Google th&#xF4;ng qua giao th&#x1EE9;c OIDC, vi&#x1EC7;c c&#x1EE7;a ch&#xFA;ng ta c&#xF2;n l&#x1EA1;i l&#xE0; c&#x1EA7;n ph&#x1EA3;i c&#x1EA5;u h&#xEC;nh &#x111;&#x1EC3; c&#xF3; giao di&#x1EC7;n &#x111;&#x103;ng nh&#x1EAD;p v&#x1EDB;i Google m&#xE0; th&#xF4;i.</p>
<h1 id="c%C3%A0i-%C4%91%E1%BA%B7t-kubelogin">C&#xE0;i &#x111;&#x1EB7;t kubelogin</h1>
<p>kubelogin l&#xE0; m&#x1ED9;t plugin c&#x1EE7;a kubectl, plugin n&#xE0;y h&#x1ED7; tr&#x1EE3; ch&#xFA;ng ta trong kh&#xE2;u login v&#x1EDB;i Google. Ph&#xED;a d&#x1B0;&#x1EDB;i l&#xE0; c&#xE1;c c&#xE2;u l&#x1EC7;nh &#x111;&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t kubelogin, ho&#x1EB7;c b&#x1EA1;n c&#xF3; th&#x1EC3; xem th&#xEA;m &#x1EDF; <a href="https://github.com/int128/kubelogin?ref=engineering.shopbase.com">github</a>.</p>
<pre><code class="language-bash"># Homebrew (macOS and Linux)
brew install int128/kubelogin/kubelogin

# Krew (macOS, Linux, Windows and ARM)
kubectl krew install oidc-login

# Chocolatey (Windows)
choco install kubelogin
</code></pre>
<h1 id="authenticate-v%E1%BB%9Bi-eks">Authenticate v&#x1EDB;i EKS</h1>
<p>Sau c&#xE1;c b&#x1B0;&#x1EDB;c c&#xE0;i &#x111;&#x1EB7;t &#x1EDF; tr&#xEA;n, cu&#x1ED1;i c&#xF9;ng ch&#xFA;ng ta c&#xF3; th&#x1EC3; login &#x111;&#x1B0;&#x1EE3;c r&#x1ED3;i!!!</p>
<p>N&#x1EBF;u c&#xE0;i &#x111;&#x1EB7;t c&#x1EE7;a ch&#xFA;ng ta l&#xE0; ch&#xED;nh x&#xE1;c, sau khi th&#x1EF1;c hi&#x1EC7;n c&#xE2;u l&#x1EC7;nh sau th&#xEC; s&#x1EBD; c&#xF3; 1 browser t&#x1EF1; &#x111;&#x1ED9;ng b&#x1EAD;t l&#xEA;n v&#xE0; d&#x1EAB;n &#x111;&#x1EBF;n trang &#x111;&#x103;ng nh&#x1EAD;p c&#x1EE7;a Google.</p>
<pre><code class="language-bash">$ kubectl oidc-login setup \
  --oidc-issuer-url https://accounts.google.com \
  --oidc-client-id=858670347920-xxxxxxxxxxx.apps.googleusercontent.com \
  --oidc-client-secret=GOCSPX-xxxxxxxxxxx \
  --oidc-extra-scope=email \
  --oidc-extra-scope=profile
</code></pre>
<p>Sau khi login th&#xE0;nh c&#xF4;ng, th&#xF4;ng tin x&#xE1;c minh c&#x1EE7;a b&#x1EA1;n s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c hi&#x1EC3;n th&#x1ECB; gi&#x1ED1;ng ph&#xED;a d&#x1B0;&#x1EDB;i:</p>
<pre><code class="language-bash">{
  &quot;iss&quot;: &quot;https://accounts.google.com&quot;,
  &quot;azp&quot;: &quot;858670347920-xxxxxxxxxxx.apps.googleusercontent.com&quot;,
  &quot;aud&quot;: &quot;858670347920-xxxxxxxxxxx.apps.googleusercontent.com&quot;,
  &quot;sub&quot;: &quot;106150655626797293240&quot;,
  &quot;hd&quot;: &quot;beeketing.net&quot;,
  &quot;email&quot;: &quot;namnguyen1@beeketing.net&quot;,
  &quot;email_verified&quot;: true,
  &quot;at_hash&quot;: &quot;KcKxEFodvK9Srkk7401q7Q&quot;,
  &quot;nonce&quot;: &quot;XLlgS7O8Fgekbj8mF6f8PS4gKyqExKpoygAnuR-w5Dc&quot;,
  &quot;name&quot;: &quot;Nam Nguyen The&quot;,
  &quot;picture&quot;: &quot;https://lh3.googleusercontent.com/a/ACg8ocJBZcSCxEI6BeijAG44YG3JcTZmBkvhD8H5tLL30vRK=s96-c&quot;,
  &quot;given_name&quot;: &quot;Nam&quot;,
  &quot;family_name&quot;: &quot;Nguyen The&quot;,
  &quot;locale&quot;: &quot;en&quot;,
  &quot;iat&quot;: 1706784878,
  &quot;exp&quot;: 1706788478
}
</code></pre>
<p>Ti&#x1EBF;p theo l&#xE0; t&#x1EA1;o config cho user OIDC trong kubeconfig th&#xF4;ng qua c&#xE2;u l&#x1EC7;nh sau:</p>
<pre><code class="language-bash">kubectl config set-credentials oidc \
	  --exec-api-version=client.authentication.k8s.io/v1beta1 \
	  --exec-command=kubectl \
	  --exec-arg=oidc-login \
	  --exec-arg=get-token \
	  --exec-arg=--oidc-issuer-url=https://accounts.google.com \
	  --exec-arg=--oidc-client-id=858670347920-xxxxxxxxxxx.apps.googleusercontent.com \
	  --exec-arg=--oidc-client-secret=GOCSPX-xxxxxxxxxxx \
	  --exec-arg=--oidc-extra-scope=email \
	  --exec-arg=--oidc-extra-scope=profile
</code></pre>
<p>Th&#x1EED; th&#x1EF1;c hi&#x1EC7;n c&#xE2;u l&#x1EC7;nh l&#x1EA5;y danh s&#xE1;ch <code>nodes</code> v&#x1EDB;i user oidc n&#xE0;y xem sao:</p>
<pre><code class="language-bash">$ kubectl --user=oidc get nodes
</code></pre>
<p>Oh, c&#xF3; v&#x1EBB; c&#xF3; l&#x1ED7;i x&#x1EA3;y ra, c&#xE2;u l&#x1EC7;nh sau khi th&#x1EF1;c hi&#x1EC7;n kh&#xF4;ng l&#x1EA5;y &#x111;&#x1B0;&#x1EE3;c danh s&#xE1;ch nodes m&#xE0; ch&#x1EC9; tr&#x1EA3; v&#x1EC1; l&#x1ED7;i:</p>
<pre><code class="language-bash">
Error from server (Forbidden): nodes is forbidden: User &quot;namnguyen1@beeketing.net&quot; cannot list resource &quot;nodes&quot; in API group &quot;&quot; at the cluster scope
</code></pre>
<p>&#x110;&#x1EEB;ng lo l&#x1EAF;ng, ch&#xFA;ng ta s&#x1EBD; &#x111;i t&#xEC;m hi&#x1EC3;u v&#x1EC1; l&#x1ED7;i n&#xE0;y ngay b&#xE2;y gi&#x1EDD; &#x111;&#xE2;y.</p>
<h2 id="ph%C3%A2n-quy%E1%BB%81n-trong-eks">Ph&#xE2;n quy&#x1EC1;n trong EKS</h2>
<p>Sau c&#xE1;c b&#x1B0;&#x1EDB;c tr&#xEA;n ch&#xFA;ng ta &#x111;&#xE3; c&#xF3; th&#x1EC3; x&#xE1;c th&#x1EF1;c v&#x1EDB;i EKS th&#xF4;ng qua Google, b&#x1EB1;ng ch&#x1EE9;ng &#x1EDF; &#x111;&#xE2;y l&#xE0; EKS &#x111;&#xE3; tr&#x1EA3; v&#x1EC1; l&#x1ED7;i v&#x1EDB;i user &#x111;&#x1ECB;nh danh l&#xE0; email c&#x1EE7;a ch&#xFA;ng ta: <code>namnguyen1@beeketing.net</code> ti&#x1EBF;p theo vi&#x1EC7;c ch&#xFA;ng ta c&#x1EA7;n l&#xE0;m l&#xE0; ph&#x1EA3;i c&#x1EA5;u h&#xEC;nh th&#xEA;m permission hay ph&#xE2;n quy&#x1EC1;n cho user sau khi &#x111;&#x1B0;&#x1EE3;c x&#xE1;c th&#x1EF1;c b&#x1EDF;i Google &#x111;&#x1B0;&#x1EE3;c th&#x1EF1;c hi&#x1EC7;n c&#xE1;c h&#xE0;nh &#x111;&#x1ED9;ng tr&#xEA;n c&#x1EE5;m EKS</p>
<pre><code class="language-bash">$ kubectl create clusterrolebinding oidc-cluster-admin --clusterrole=cluster-admin --user=&apos;namnguyen1@beeketing.net&apos;
</code></pre>
<p>C&#xF9;ng th&#x1EED; l&#x1EA1;i command tr&#xEA;n xem sao, v&#xE0; ch&#xFA;ng ta &#x111;&#xE3; l&#x1EA5;y &#x111;&#x1B0;&#x1EE3;c th&#xF4;ng tin c&#xE1;c nodes trong c&#x1EE5;m EKS th&#xF4;ng qua token vi&#x1EC7;c login b&#x1EB1;ng account Google</p>
<pre><code class="language-bash">$ kubectl --user=oidc get nodes

NAME                                              STATUS                        ROLES    AGE     VERSION
ip-10-30-1-230.ap-southeast-1.compute.internal    Ready                         &lt;none&gt;   10m     v1.24.7-eks-fb459a0
ip-10-30-12-56.ap-southeast-1.compute.internal    Ready                         &lt;none&gt;   15m     v1.24.7-eks-fb459a0
</code></pre>
<p>T&#x1EEB; &#x111;&#xE2;y b&#x1EA1;n c&#x169;ng c&#xF3; th&#x1EC3; chia s&#x1EBB; c&#x1EA5;u h&#xEC;nh oidc n&#xE0;y cho members kh&#xE1;c, v&#xE0; h&#x1ECD; c&#x169;ng s&#x1EBD; c&#xF3; th&#x1EC3; authenticate v&#x1EDB;i EKS th&#xF4;ng qua account Google c&#x1EE7;a h&#x1ECD;.</p>
<h1 id="t%E1%BB%95ng-k%E1%BA%BFt">T&#x1ED5;ng k&#x1EBF;t</h1>
<p>Vi&#x1EC7;c t&#xED;ch h&#x1EE3;p Google v&#xE0;o kh&#xE2;u x&#xE1;c th&#x1EF1;c EKS hay b&#x1EA5;t k&#x1EF3; &#x1EE9;ng d&#x1EE5;ng n&#xE0;o &#x111;em l&#x1EA1;i s&#x1EF1; linh ho&#x1EA1;t trong kh&#xE2;u qu&#x1EA3;n l&#xFD;, gi&#xFA;p ti&#x1EBF;t ki&#x1EC7;m th&#x1EDD;i gian v&#xE0; c&#xF4;ng s&#x1EE9;c trong vi&#x1EC7;c v&#x1EAD;n h&#xE0;nh c&#x1EE5;m, &#x111;&#x1EB7;c bi&#x1EC7;t l&#xE0; v&#x1EDB;i quy m&#xF4; nh&#xE2;n s&#x1EF1; l&#x1EDB;n. Tuy nhi&#xEA;n trong th&#x1EF1;c t&#x1EBF; vi&#x1EC7;c t&#xED;ch h&#x1EE3;p OIDC v&#x1EDB;i tr&#x1EF1;c ti&#x1EBF;p Google l&#xE0; t&#x1B0;&#x1A1;ng &#x111;&#x1ED1;i hi&#x1EBF;m, b&#x1EDF;i v&#xEC; nh&#x1EEF;ng claims</p>
<h1 id="t%C3%A0i-li%E1%BB%87u-tham-kh%E1%BA%A3o">T&#xE0;i li&#x1EC7;u tham kh&#x1EA3;o</h1>
<ul>
<li><a href="https://github.com/int128/kubelogin?ref=engineering.shopbase.com">https://github.com/int128/kubelogin</a></li>
<li><a href="https://docs.aws.amazon.com/eks/latest/userguide/authenticate-oidc-identity-provider.html?ref=engineering.shopbase.com">https://docs.aws.amazon.com/eks/latest/userguide/authenticate-oidc-identity-provider.html</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Bloom Filter - Công Cụ Mạnh Mẽ Trong Xử Lý Dữ Liệu]]></title><description><![CDATA[<p></p><p><em>Trong th&#x1EBF; k&#x1EF7; 21, vi&#x1EC7;c x&#x1EED; l&#xFD; d&#x1EEF; li&#x1EC7;u l&#xE0; m&#x1ED9;t ph&#x1EA7;n kh&#xF4;ng th&#x1EC3; thi&#x1EBF;u c&#x1EE7;a cu&#x1ED9;c s&#x1ED1;ng h&#xE0;ng ng&#xE0;y c&</em></p>]]></description><link>https://engineering.shopbase.com/bloom-filter/</link><guid isPermaLink="false">65bb10f595b8649d9ab036e7</guid><dc:creator><![CDATA[Tra Luong]]></dc:creator><pubDate>Thu, 01 Feb 2024 06:39:52 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/x.png" medium="image"/><content:encoded><![CDATA[<img src="https://engineering.shopbase.com/content/images/2024/02/x.png" alt="Bloom Filter - C&#xF4;ng C&#x1EE5; M&#x1EA1;nh M&#x1EBD; Trong X&#x1EED; L&#xFD; D&#x1EEF; Li&#x1EC7;u"><p></p><p><em>Trong th&#x1EBF; k&#x1EF7; 21, vi&#x1EC7;c x&#x1EED; l&#xFD; d&#x1EEF; li&#x1EC7;u l&#xE0; m&#x1ED9;t ph&#x1EA7;n kh&#xF4;ng th&#x1EC3; thi&#x1EBF;u c&#x1EE7;a cu&#x1ED9;c s&#x1ED1;ng h&#xE0;ng ng&#xE0;y c&#x1EE7;a ch&#xFA;ng ta. Tuy nhi&#xEA;n, vi&#x1EC7;c l&#x1B0;u tr&#x1EEF; v&#xE0; truy xu&#x1EA5;t d&#x1EEF; li&#x1EC7;u nhanh ch&#xF3;ng c&#xF3; th&#x1EC3; tr&#x1EDF; th&#xE0;nh m&#x1ED9;t nhi&#x1EC7;m v&#x1EE5; ph&#x1EE9;c t&#x1EA1;p v&#xE0; &#x111;&#xE1;ng t&#x1ED1;n k&#xE9;m. Do &#x111;&#xF3; c&#x1EA7;n c&#xF3; nh&#x1EEF;ng k&#x1EF9; thu&#x1EAD;t t&#x1B0;&#x1A1;ng &#x1EE9;ng &#x111;&#x1EC3; &#x111;&#xE1;p &#x1EE9;ng &#x111;&#x1B0;&#x1EE3;c nhu c&#x1EA7;u n&#xE0;y, c&#x169;ng l&#xE0; nguy&#xEA;n nh&#xE2;n s&#x1EF1; ra &#x111;&#x1EDD;i c&#x1EE7;a Bloom Filter.</em></p><h2 id="bloom-filter-l%C3%A0-g%C3%AC">Bloom Filter l&#xE0; g&#xEC;?</h2><p></p><p>Bloom Filter l&#xE0; m&#x1ED9;t c&#x1EA5;u tr&#xFA;c d&#x1EEF; li&#x1EC7;u &#x111;&#x1B0;&#x1EE3;c ph&#xE1;t tri&#x1EC3;n b&#x1EDF;i Burton H. Bloom v&#xE0;o n&#x103;m 1970, khi &#xF4;ng l&#xE0; m&#x1ED9;t nh&#xE0; nghi&#xEA;n c&#x1EE9;u t&#x1EA1;i Xerox Corporation&apos;s Palo Alto Research Center (PARC). &#xD4;ng c&#xF4;ng b&#x1ED1; &#xFD; t&#x1B0;&#x1EDF;ng v&#x1EC1; Bloom Filter trong b&#xE0;i b&#xE1;o &quot;Space/Time Trade-offs in Hash Coding with Allowable Errors&quot; v&#xE0;o n&#x103;m 1970.</p><p>M&#x1ED9;t trong nh&#x1EEF;ng &#x111;i&#x1EC3;m quan tr&#x1ECD;ng c&#x1EE7;a Bloom Filter l&#xE0; kh&#x1EA3; n&#x103;ng ki&#x1EC3;m tra s&#x1EF1; t&#x1ED3;n t&#x1EA1;i c&#x1EE7;a m&#x1ED9;t ph&#x1EA7;n t&#x1EED; trong m&#x1ED9;t t&#x1EAD;p h&#x1EE3;p l&#x1EDB;n m&#xE0; kh&#xF4;ng c&#x1EA7;n l&#x1B0;u tr&#x1EEF; t&#x1EA5;t c&#x1EA3; c&#xE1;c ph&#x1EA7;n t&#x1EED;. Tuy nhi&#xEA;n, Bloom Filter c&#xF3; m&#x1ED9;t s&#x1ED1; h&#x1EA1;n ch&#x1EBF; quan tr&#x1ECD;ng, bao g&#x1ED3;m kh&#x1EA3; n&#x103;ng false positive (khi Bloom Filter b&#xE1;o r&#x1EB1;ng m&#x1ED9;t ph&#x1EA7;n t&#x1EED; t&#x1ED3;n t&#x1EA1;i trong t&#x1EAD;p h&#x1EE3;p m&#x1EB7;c d&#xF9; th&#x1EF1;c t&#x1EBF; kh&#xF4;ng c&#xF3;) v&#xE0; kh&#xF4;ng th&#x1EC3; lo&#x1EA1;i b&#x1ECF; ph&#x1EA7;n t&#x1EED; &#x111;&#xE3; th&#xEA;m v&#xE0;o.</p><h2 id="bloom-filter-ho%E1%BA%A1t-%C4%91%E1%BB%99ng-nh%C6%B0-th%E1%BA%BF-n%C3%A0o"><strong>Bloom Filter ho&#x1EA1;t &#x111;&#x1ED9;ng nh&#x1B0; th&#x1EBF; n&#xE0;o?</strong></h2><p></p><p>Bloom Filter xu&#x1EA5;t ph&#xE1;t t&#x1EEB; nhu c&#x1EA7;u t&#x1ED1;i &#x1B0;u h&#xF3;a vi&#x1EC7;c t&#xEC;m ki&#x1EBF;m - kh&#x1EA3; n&#x103;ng ki&#x1EC3;m tra s&#x1EF1; t&#x1ED3;n t&#x1EA1;i c&#x1EE7;a m&#x1ED9;t ph&#x1EA7;n t&#x1EED; trong m&#x1ED9;t t&#x1EAD;p h&#x1EE3;p l&#x1EDB;n m&#xE0; kh&#xF4;ng c&#x1EA7;n l&#x1B0;u tr&#x1EEF; t&#x1EA5;t c&#x1EA3; c&#xE1;c ph&#x1EA7;n t&#x1EED;. &#xDD; t&#x1B0;&#x1EDF;ng v&#x1EC1; c&#xE1;ch ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a Bloom Filter c&#xF3; th&#x1EC3; m&#xF4; t&#x1EA3; ng&#x1EAF;n g&#x1ECD;n nh&#x1B0; sau: T&#x1EEB; gi&#xE1; tr&#x1ECB; <strong><em>x</em></strong> thu&#x1ED9;c t&#x1EAD;p<strong><em> X</em></strong>, ta t&#x1EA1;o ra m&#x1ED9;t gi&#xE1; tr&#x1ECB; <strong><em>y = h(x)</em></strong> thu&#x1ED9;c t&#x1EAD;p <strong><em>Y</em></strong>, v&#x1EDB;i h l&#xE0; m&#x1ED9;t hash function. Sau &#x111;&#xF3; ta c&#xF3; th&#x1EC3; ki&#x1EC3;m tra gi&#xE1; tr&#x1ECB; <strong><em>x&apos;</em></strong> c&#xF3; thu&#x1ED9;c <strong><em>X</em></strong> kh&#xF4;ng b&#x1EB1;ng c&#xE1;ch ki&#x1EC3;m tra xem<em><strong> y&apos; = h(x&apos;)</strong> </em>c&#xF3; thu&#x1ED9;c t&#x1EAD;p <strong><em>Y</em></strong> hay kh&#xF4;ng.</p><p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y ta s&#x1EBD; gi&#x1EDB;i thi&#x1EC7;u chi ti&#x1EBF;t c&#xE1;ch ho&#x1EA1;t &#x111;&#x1ED9;ng:</p><h4 id="kh%E1%BB%9Fi-t%E1%BA%A1o-bloom-filter">Kh&#x1EDF;i t&#x1EA1;o Bloom Filter</h4><ul><li>Bloom Filter bao g&#x1ED3;m m&#x1ED9;t bit array v&#x1EDB;i m bits ban &#x111;&#x1EA7;u &#x111;&#x1B0;&#x1EE3;c thi&#x1EBF;t l&#x1EAD;p th&#xE0;nh gi&#xE1; tr&#x1ECB; <strong>0</strong>.</li><li>Ch&#x1ECD;n <strong><em>k</em></strong> hash function, m&#x1ED7;i hash function hash m&#x1ED9;t t&#x1EAD;p gi&#xE1; tr&#x1ECB; v&#xE0;o <strong><em>m</em></strong> v&#x1ECB; tr&#xED; tr&#xEA;n bit array. T&#x1EA1;o n&#xEA;n ph&#xE2;n ph&#x1ED1;i x&#xE1;c su&#x1EA5;t ng&#x1EAB;u nhi&#xEA;n tr&#xEA;n m&#x1EA3;ng.</li><li>Hai tham s&#x1ED1; quan tr&#x1ECD;ng c&#x1EA7;n x&#xE1;c &#x111;&#x1ECB;nh tr&#x1B0;&#x1EDB;c khi t&#x1EA1;o Bloom Filter l&#xE0; <strong><em>m</em></strong> - k&#xED;ch th&#x1B0;&#x1EDB;c bit array v&#xE0; <strong><em>k</em></strong> s&#x1ED1; l&#x1B0;&#x1EE3;ng hash function l&#xE0; hai tham s&#x1ED1; quan tr&#x1ECD;ng c&#x1EA7;n x&#xE1;c &#x111;&#x1ECB;nh tr&#x1B0;&#x1EDB;c khi t&#x1EA1;o Bloom Filter. Hai tham s&#x1ED1; n&#xE0;y t&#x1EC9; l&#x1EC7; thu&#x1EAD;n v&#x1EDB;i nhau v&#xE0; t&#x1EC9; l&#x1EC7; thu&#x1EAD;n v&#x1EDB;i s&#x1ED1; l&#x1B0;&#x1EE3;ng ph&#x1EA7;n t&#x1EED; trong t&#x1EAD;p.</li></ul><h4 id="th%C3%AAm-ph%E1%BA%A7n-t%E1%BB%AD-v%C3%A0o-bloom-filter">Th&#xEA;m ph&#x1EA7;n t&#x1EED; v&#xE0;o Bloom Filter</h4><ul><li>Khi m&#x1ED9;t ph&#x1EA7;n t&#x1EED; &#x111;&#x1B0;&#x1EE3;c th&#xEA;m v&#xE0;o Bloom Filter, ta th&#x1EF1;c hi&#x1EC7;n <strong><em>k </em></strong>hash function &#x111;&#x1ED9;c l&#x1EAD;p thu &#x111;&#x1B0;&#x1EE3;c<strong><em> k </em></strong>gi&#xE1; tr&#x1ECB;.</li><li>K gi&#xE1; tr&#x1ECB; sau khi hash s&#x1EBD; n&#x1EB1;m trong &#x111;o&#x1EA1;n <strong><em>[0, m-1]</em></strong>, t&#x1B0;&#x1A1;ng &#x1EE9;ng v&#x1EDB;i c&#xE1;c v&#x1ECB; tr&#xED; tr&#xEA;n bit array.</li><li>V&#x1EDB;i m&#x1ED7;i gi&#xE1; tr&#x1ECB; sau khi hash, ta set bit t&#x1EA1;i v&#x1ECB; tr&#xED; &#x111;&#xF3; = 1</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ilyasergey.net/YSC2229/_images/bloom.png" class="kg-image" alt="Bloom Filter - C&#xF4;ng C&#x1EE5; M&#x1EA1;nh M&#x1EBD; Trong X&#x1EED; L&#xFD; D&#x1EEF; Li&#x1EC7;u" loading="lazy"><figcaption><span style="white-space: pre-wrap;">Bloom Filter with 15 bits array with 3 hash functions</span></figcaption></figure><h4 id="ki%E1%BB%83m-tra-s%E1%BB%B1-t%E1%BB%93n-t%E1%BA%A1i-c%E1%BB%A7a-ph%E1%BA%A7n-t%E1%BB%AD">Ki&#x1EC3;m tra s&#x1EF1; t&#x1ED3;n t&#x1EA1;i c&#x1EE7;a ph&#x1EA7;n t&#x1EED;</h4><ul><li>Khi mu&#x1ED1;n ki&#x1EC3;m tra s&#x1EF1; t&#x1ED3;n t&#x1EA1;i c&#x1EE7;a m&#x1ED9;t ph&#x1EA7;n t&#x1EED; trong Bloom Filter, ta l&#x1EB7;p l&#x1EA1;i c&#xE1;c b&#x1B0;&#x1EDB;c t&#x1B0;&#x1A1;ng t&#x1EF1;: th&#x1EF1;c hi&#x1EC7;n k hash function v&#xE0; thu &#x111;&#x1B0;&#x1EE3;c k gi&#xE1; tr&#x1ECB; t&#x1B0;&#x1A1;ng &#x1EE9;ng trong &#x111;o&#x1EA1;n <strong><em>[0, m-1]</em></strong></li><li>Ki&#x1EC3;m tra k v&#x1ECB; tr&#xED; bit n&#xE0;y trong m&#x1EA3;ng bit. N&#x1EBF;u t&#x1EA5;t c&#x1EA3; c&#xE1;c bit &#x1EDF; k v&#x1ECB; tr&#xED; n&#xE0;y &#x111;&#x1EC1;u b&#x1EB1;ng 1. Bloom Filter cho r&#x1EB1;ng ph&#x1EA7;n t&#x1EED; <strong>c&#xF3; th&#x1EC3; </strong>t&#x1ED3;n t&#x1EA1;i trong t&#x1EAD;p h&#x1EE3;p. <em>(step 3.1)</em></li><li>Ki&#x1EC3;m tra k v&#x1ECB; tr&#xED; bit n&#xE0;y trong m&#x1EA3;ng bit. N&#x1EBF;u &#xED;t nh&#x1EA5;t m&#x1ED9;t v&#x1ECB; tr&#xED; bit l&#xE0; 0, Bloom Filter kh&#x1EB3;ng &#x111;&#x1ECB;nh ph&#x1EA7;n t&#x1EED; kh&#xF4;ng t&#x1ED3;n t&#x1EA1;i trong t&#x1EAD;p h&#x1EE3;p. <em>(step 3.2)</em></li></ul><h4 id="false-positive">False positive</h4><p>Qua vi&#x1EC7;c t&#xEC;m hi&#x1EC3;u c&#xE1;ch ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a Bloom Filter ta c&#xF3; th&#x1EC3; th&#x1EA5;y r&#x1EB1;ng. Bloom Filter c&#xF3; th&#x1EC3; kh&#x1EB3;ng &#x111;&#x1ECB;nh ch&#x1EAF;c ch&#x1EAF;n m&#x1ED9;t ph&#x1EA7;n t&#x1EED; kh&#xF4;ng t&#x1ED3;n t&#x1EA1;i trong t&#x1EAD;p h&#x1EE3;p<em> (step 3.2)</em>, nh&#x1B0;ng &#x1EDF; chi&#x1EC1;u ng&#x1B0;&#x1EE3;c l&#x1EA1;i kh&#xF4;ng th&#x1EC3; kh&#x1EB3;ng &#x111;&#x1ECB;nh ch&#x1EAF;c ch&#x1EAF;n l&#xE0; ph&#x1EA7;n t&#x1EED; n&#xE0;y thu&#x1ED9;c t&#x1EAD;p h&#x1EE3;p <em>(step 3.1)</em>. &#x110;&#xE2;y c&#x169;ng l&#xE0; nh&#x1B0;&#x1EE3;c &#x111;i&#x1EC3;m c&#x1EE7;a Bloom Filter.</p><ul><li>Bloom Filter c&#xF3; kh&#x1EA3; n&#x103;ng g&#xE2;y ra false positive. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; ngh&#x129;a l&#xE0; Bloom Filter c&#xF3; th&#x1EC3; b&#xE1;o nh&#x1EA7;m r&#x1EB1;ng m&#x1ED9;t ph&#x1EA7;n t&#x1EED; t&#x1ED3;n t&#x1EA1;i trong t&#x1EAD;p h&#x1EE3;p m&#x1EB7;c d&#xF9; th&#x1EF1;c t&#x1EBF; kh&#xF4;ng c&#xF3;.</li><li>Kh&#x1EA3; n&#x103;ng false positive t&#x103;ng l&#xEA;n khi k&#xED;ch th&#x1B0;&#x1EDB;c c&#x1EE7;a bit array <em>(<strong>m</strong>)</em> nh&#x1ECF; ho&#x1EB7;c s&#x1ED1; l&#x1B0;&#x1EE3;ng hash function (<em><strong>k</strong>)<strong> </strong></em> b&#xE9;. &#x110;&#x1EC3; gi&#x1EA3;m false positive, b&#x1EA1;n c&#xF3; th&#x1EC3; t&#x103;ng k&#xED;ch th&#x1B0;&#x1EDB;c m&#x1EA3;ng bit ho&#x1EB7;c s&#x1ED1; l&#x1B0;&#x1EE3;ng h&#xE0;m b&#x103;m, nh&#x1B0;ng &#x111;i&#x1EC1;u n&#xE0;y &#x111;&#x1ED3;ng ngh&#x129;a v&#x1EDB;i vi&#x1EC7;c t&#x103;ng s&#x1EED; d&#x1EE5;ng b&#x1ED9; nh&#x1EDB; v&#xE0; t&#x103;ng &#x111;&#x1ED9; ph&#x1EE9;c t&#x1EA1;p t&#xED;nh to&#xE1;n.</li></ul><h4 id="immutable">Immutable</h4><p>M&#x1ED9;t trong nh&#x1EEF;ng &#x111;&#x1EB7;c t&#xED;nh v&#xE0; c&#x169;ng l&#xE0; h&#x1EA1;n ch&#x1EBF; c&#x1EE7;a Bloom Filter l&#xE0; kh&#xF4;ng th&#x1EC3; thay &#x111;&#x1ED5;i. C&#x1EE5; th&#x1EC3; &#x1EDF; &#x111;&#xE2;y l&#xE0; vi&#x1EC7;c lo&#x1EA1;i b&#x1ECF; m&#x1ED9;t ph&#x1EA7;n t&#x1EED; ra kh&#x1ECF;i t&#x1EAD;p h&#x1EE3;p l&#xE0; kh&#xF4;ng th&#x1EC3;, qua c&#xE1;ch ho&#x1EA1;t &#x111;&#x1ED9;ng ta c&#xF3; th&#x1EC3; th&#x1EA5;y kh&#xF4;ng c&#xF3; c&#xE1;ch n&#xE0;o lo&#x1EA1;i b&#x1ECF; ph&#x1EA7;n t&#x1EED; kh&#x1ECF;i t&#x1EAD;p h&#x1EE3;p m&#xE0; v&#x1EAB;n &#x111;&#x1EA3;m b&#x1EA3;o t&#xED;nh ch&#xED;nh x&#xE1;c c&#x1EE7;a bit array. &#x110;i&#x1EC1;u n&#xE0;y l&#xE0;m cho Bloom Filter th&#xED;ch h&#x1EE3;p cho c&#xE1;c &#x1EE9;ng d&#x1EE5;ng m&#xE0; t&#x1EAD;p h&#x1EE3;p d&#x1EEF; li&#x1EC7;u l&#xE0; c&#x1ED1; &#x111;&#x1ECB;nh v&#xE0; kh&#xF4;ng thay &#x111;&#x1ED5;i th&#x1B0;&#x1EDD;ng xuy&#xEA;n.</p><h2 id="counting-bloom-filter">Counting Bloom Filter</h2><p>Do c&#xF3; nh&#x1EEF;ng h&#x1EA1;n ch&#x1EBF; nh&#x1B0; tr&#xEA;n. Vi&#x1EC7;c apply tr&#x1EF1;c ti&#x1EBF;p Bloom Filter v&#xE0;o c&#xE1;c b&#xE0;i to&#xE1;n &#x111;&#x1EB7;c th&#xF9; g&#x1EB7;p kh&#xF3; kh&#x103;n, &#x111;&#xF3; c&#x169;ng l&#xE0; l&#xFD; do ra &#x111;&#x1EDD;i cho c&#xE1;c bi&#x1EBF;n th&#x1EC3;. M&#x1ED9;t trong s&#x1ED1; &#x111;&#xF3; c&#xF3; th&#x1EC3; k&#x1EC3; &#x111;&#x1EBF;n l&#xE0; Counting Bloom Filter.</p><p>Cho m&#x1ED9;t ph&#x1EA7;n t&#x1EED; <strong><em>x</em></strong> v&#xE0; m&#x1ED9;t t&#x1EAD;p <strong><em>X</em></strong>. Counting Bloom Filter cho ph&#xE9;p truy v&#x1EA5;n ki&#x1EC3;m tra s&#x1ED1; l&#x1B0;&#x1EE3;t xu&#x1EA5;t hi&#x1EC7;n trong <strong><em>X</em></strong> c&#x1EE7;a <strong><em>x</em></strong>: cho <strong><em>x</em></strong> v&#xE0; m&#x1ED9;t thresh hold number <strong><em>k</em></strong>. Counting Bloom Filter tr&#x1EA3; v&#x1EC1; ch&#x1EAF;c ch&#x1EAF;n s&#x1ED1; t&#x1ED3;n t&#x1EA1;i c&#x1EE7;a <strong><em>x</em></strong> trong <strong><em>X</em></strong> b&#xE9; h&#x1A1;n <strong><em>k</em></strong>, ho&#x1EB7;c c&#xF3; th&#x1EC3; l&#x1EDB;n h&#x1A1;n ho&#x1EB7;c b&#x1EB1;ng<strong><em> k</em></strong>.</p><p>D&#x1EC5; th&#x1EA5;y vi&#x1EC7;c n&#xE0;y c&#xF3; th&#x1EC3; th&#x1EF1;c hi&#x1EC7;n &#x111;&#x1A1;n gi&#x1EA3;n th&#xF4;ng qua vi&#x1EC7;c thay &#x111;&#x1ED5;i c&#xE1;ch th&#xEA;m ph&#x1EA7;n t&#x1EED; v&#xE0;o t&#x1EAD;p. Thay v&#xEC; set <em>bit = 1</em> nh&#x1B0; Bloom Filter, Counting Bloom Filter <em>th&#xEA;m 1 v&#xE0;o bit</em>. Qua c&#x1A1; ch&#x1EBF; tr&#xEA;n, vi&#x1EC7;c xo&#xE1; ph&#x1EA7;n t&#x1EED; ra kh&#x1ECF;i t&#x1EAD;p ban &#x111;&#x1EA7;u l&#xE0; ho&#xE0;n to&#xE0;n c&#xF3; th&#x1EC3;. Tuy nhi&#xEA;n vi&#x1EC7;c n&#xE0;y c&#x169;ng g&#xE2;y n&#xEA;n t&#x103;ng false positive rate khi m&#xE0; ph&#x1EA7;n t&#x1EED; &#x111;&#x1B0;&#x1EE3;c xo&#xE1; kh&#xF4;ng t&#x1ED3;n t&#x1EA1;i kh&#xF4;ng t&#x1EAD;p ban &#x111;&#x1EA7;u.</p><p>Ngo&#xE0;i ra c&#xF2;n m&#x1ED9;t s&#x1ED1; bi&#x1EBF;n th&#x1EC3; kh&#xE1;c c&#x1EE7;a Bloom Filter c&#x169;ng &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng r&#x1ED9;ng r&#xE3;i nh&#x1B0;:</p><ol><li><strong>Dynamic Bloom Filter</strong>: Cho ph&#xE9;p th&#xEA;m v&#xE0; x&#xF3;a ph&#x1EA7;n t&#x1EED; t&#x1EEB; Bloom Filter, ph&#xF9; h&#x1EE3;p cho c&#xE1;c t&#xEC;nh hu&#x1ED1;ng c&#x1EA7;n thay &#x111;&#x1ED5;i t&#x1EAD;p d&#x1EEF; li&#x1EC7;u th&#x1B0;&#x1EDD;ng xuy&#xEA;n.</li><li><strong>Bloomier Filters</strong>: C&#x1EA3;i ti&#x1EBF;n c&#x1EE7;a Bloom Filter v&#x1EDB;i kh&#x1EA3; n&#x103;ng tr&#x1EA3; l&#x1EDD;i c&#xE2;u h&#x1ECF;i ki&#x1EC3;u &quot;n&#x1EBF;u kh&#xF4;ng c&#xF3; d&#x1EEF; li&#x1EC7;u n&#xE0;y, th&#xEC; c&#xF3; d&#x1EEF; li&#x1EC7;u n&#xE0;o g&#x1EA7;n gi&#x1ED1;ng kh&#xF4;ng?&quot;.</li></ol><h2 id="%E1%BB%A9ng-d%E1%BB%A5ng-c%E1%BB%A7a-bloom-filter-trong-c%C3%A1c-b%C3%A0i-to%C3%A1n-th%E1%BB%B1c-t%E1%BA%BF"><strong>&#x1EE8;ng d&#x1EE5;ng c&#x1EE7;a Bloom Filter trong c&#xE1;c b&#xE0;i to&#xE1;n th&#x1EF1;c t&#x1EBF;</strong></h2><p></p><p>Sau khi c&#xF4;ng b&#x1ED1;, Bloom Filter &#x111;&#xE3; t&#xEC;m th&#x1EA5;y nhi&#x1EC1;u &#x1EE9;ng d&#x1EE5;ng trong th&#x1EBF; gi&#x1EDB;i th&#x1EF1;c v&#xE0; tr&#x1EDF; th&#xE0;nh m&#x1ED9;t c&#xF4;ng c&#x1EE5; h&#x1EEF;u &#xED;ch trong l&#x129;nh v&#x1EF1;c x&#x1EED; l&#xFD; d&#x1EEF; li&#x1EC7;u v&#xE0; t&#x1ED1;i &#x1B0;u h&#xF3;a hi&#x1EC7;u su&#x1EA5;t. N&#xF3; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng r&#x1ED9;ng r&#xE3;i trong c&#xE1;c h&#x1EC7; th&#x1ED1;ng c&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u l&#x1EDB;n, l&#x1ECD;c th&#x1B0; r&#xE1;c, ki&#x1EC3;m tra s&#x1EF1; t&#x1ED3;n t&#x1EA1;i c&#x1EE7;a d&#x1EEF; li&#x1EC7;u trong b&#x1ED9; nh&#x1EDB; &#x111;&#x1EC7;m, v&#xE0; nhi&#x1EC1;u &#x1EE9;ng d&#x1EE5;ng kh&#xE1;c.</p><h4 id="cache-filtering">Cache filtering</h4><p>C&#xE1;c h&#x1EC7; th&#x1ED1;ng CDN caching web content &#x111;&#x1EBF;n nhi&#x1EC1;u user &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o performance, latency v&#xE0; network bandwidth. G&#x1EA7;n ba ph&#x1EA7;n t&#x1B0; c&#xE1;c URL &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p t&#x1EEB; c&#xE1;c trang web ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p m&#x1ED9;t l&#x1EA7;n v&#xE0; kh&#xF4;ng bao gi&#x1EDD; &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p l&#x1EA1;i. Vi&#x1EC7;c cache l&#x1EA1;i c&#xE1;c content n&#xE0;y l&#xE0; kh&#xF4;ng c&#x1EA7;n thi&#x1EBF;t v&#xE0; l&#xE3;ng ph&#xED; t&#xE0;i nguy&#xEA;n h&#x1EC7; th&#x1ED1;ng. M&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng quan tr&#x1ECD;ng c&#x1EE7;a Bloom Filter l&#xE0; vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng ch&#xFA;ng m&#x1ED9;t c&#xE1;ch hi&#x1EC7;u qu&#x1EA3; &#x111;&#x1EC3; x&#xE1;c &#x111;&#x1ECB;nh content n&#xE0;o n&#xEA;n &#x111;&#x1B0;&#x1EE3;c cache. &#x110;&#x1EC3; ng&#x103;n ch&#x1EB7;n cache c&#xE1;c content ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p m&#x1ED9;t l&#x1EA7;n, m&#x1ED9;t Bloom Filter &#x111;&#x1B0;&#x1EE3;c s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; theo d&#xF5;i t&#x1EA5;t c&#x1EA3; c&#xE1;c URL &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p b&#x1EDF;i ng&#x1B0;&#x1EDD;i d&#xF9;ng. Content &#x111;&#x1B0;&#x1EE3;c cache ch&#x1EC9; khi n&#xF3; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p &#xED;t nh&#x1EA5;t m&#x1ED9;t l&#x1EA7;n tr&#x1B0;&#x1EDB;c &#x111;&#xF3;, t&#x1EE9;c l&#xE0; content ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c cache khi c&#xF3; &#xED;t nh&#x1EA5;t 2 request t&#x1EDB;i n&#xF3;. Vi&#x1EC7;c lo&#x1EA1;i b&#x1ECF; nh&#x1EEF;ng content ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c truy c&#x1EAD;p m&#x1ED9;t l&#x1EA7;n ti&#x1EBF;t ki&#x1EC7;m &#x111;&#xE1;ng k&#x1EC3; b&#x1ED9; nh&#x1EDB;, t&#x103;ng t&#x1EC9; l&#x1EC7; hit rate.</p><figure class="kg-card kg-image-card"><img src="https://icircuit.net/wp-content/uploads/2020/12/image-3-1024x635.png" class="kg-image" alt="Bloom Filter - C&#xF4;ng C&#x1EE5; M&#x1EA1;nh M&#x1EBD; Trong X&#x1EED; L&#xFD; D&#x1EEF; Li&#x1EC7;u" loading="lazy"></figure><p></p><h4 id="ki%E1%BB%83m-tra-password-y%E1%BA%BFu">Ki&#x1EC3;m tra password y&#x1EBF;u</h4><p>Ng&#xE0;y nay vi&#x1EC7;c &#x111;&#x1EB7;t password y&#x1EBF;u l&#xE0; s&#x1EBD; d&#x1EAB;n &#x111;&#x1EBF;n nhi&#x1EC1;u r&#x1EE7;i ro. Attacker c&#xF3; th&#x1EC3; d&#x1EC5; d&#xE0;ng brute force tr&#xEA;n t&#x1EAD;p password hay &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t ho&#x1EB7;c t&#x1EAD;p password &#x111;&#xE3; b&#x1ECB; leak &#x111;&#x1EC3; chi&#x1EBF;m t&#xE0;i kho&#x1EA3;n. &#xDD; t&#x1B0;&#x1EDF;ng c&#x1EE7;a vi&#x1EC7;c n&#xE0;y l&#xE0; l&#x1B0;u m&#x1ED9;t t&#x1EAD;p d&#x1EEF; li&#x1EC7;u bao g&#x1ED3;m c&#xE1;c password y&#x1EBF;u v&#xE0; check match khi user &#x111;&#x1EB7;t password. Vi&#x1EC7;c n&#xE0;y c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c check nhanh ch&#xF3;ng b&#x1EB1;ng Bloom Filter, nhanh nh&#x1B0; hash map nh&#x1B0;ng l&#x1EA1;i t&#x1ED1;n &#xED;t space h&#x1A1;n. D&#x1EC5; d&#xE0;ng ho&#x1EA1;t &#x111;&#x1ED9;ng tr&#xEA;n t&#x1EAD;p data l&#x1EDB;n.</p><h5 id="%E1%BB%A9ng-d%E1%BB%A5ng-trong-m%E1%BA%A1ng-x%C3%A3-h%E1%BB%99i-v%C3%A0-qu%E1%BA%A3ng-c%C3%A1o"><strong>&#x1EE8;ng D&#x1EE5;ng trong M&#x1EA1;ng X&#xE3; H&#x1ED9;i v&#xE0; Qu&#x1EA3;ng C&#xE1;o</strong></h5><p>C&#xE1;c c&#xF4;ng ty ho&#x1EA1;t &#x111;&#x1ED9;ng trong m&#x1EA1;ng x&#xE3; h&#x1ED9;i v&#xE0; qu&#x1EA3;ng c&#xE1;o c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng Bloom Filter &#x111;&#x1EC3; ki&#x1EC3;m tra xem m&#x1ED9;t ng&#x1B0;&#x1EDD;i d&#xF9;ng ho&#x1EB7;c m&#x1ED9;t qu&#x1EA3;ng c&#xE1;o &#x111;&#xE3; xu&#x1EA5;t hi&#x1EC7;n tr&#x1B0;&#x1EDB;c &#x111;&#xF3; hay ch&#x1B0;a, &#x111;&#x1EC3; tr&#xE1;nh hi&#x1EC3;n th&#x1ECB; n&#x1ED9;i dung tr&#xF9;ng l&#x1EB7;p.</p><p>Nhi&#x1EC1;u c&#xF4;ng ty l&#x1EDB;n &#x111;&#xE3; &#xE1;p d&#x1EE5;ng Bloom Filter &#x111;&#x1EC3; x&#x1EED; l&#xFD; cho c&#xE1;c b&#xE0;i to&#xE1;n c&#x1EE7;a h&#x1ECD;:</p><ul><li>Akamai CDN d&#xF9;ng Bloom Filter &#x111;&#x1EC3; lo&#x1EA1;i b&#x1ECF; c&#xE1;c request m&#x1ED9;t l&#x1EA7;n &#x111;&#x1EBF;n disk cache. Akamai c&#x169;ng l&#xE0; c&#xF4;ng ty ph&#xE1;t hi&#x1EC7;n ra r&#x1EB1;ng g&#x1EA7;n 75% request t&#x1EEB; user &#x111;&#x1EBF;n server c&#x1EE7;a h&#x1ECD; ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1ECD;c m&#x1ED9;t l&#x1EA7;n. </li><li>Google&#xA0;BigTable, Apache HBase, Apache Cassandra v&#xE0; c&#x1EA3; PostgreSQL &#x111;&#x1EC1;u d&#xF9;ng Bloom Filter &#x111;&#x1EC3; ki&#x1EC3;m tra content c&#xF3; t&#x1ED3;n t&#x1EA1;i kh&#xF4;ng tr&#x1B0;&#x1EDB;c khi query v&#xE0;o disk. Gi&#x1EA3;m disk lookups v&#xE0; t&#x103;ng &#x111;&#xE1;ng k&#x1EC3; hi&#x1EC7;u su&#x1EA5;t query.</li><li>Google Chrome&#xA0;browser &#x111;&#xE3; t&#x1EEB;n d&#xF9;ng Bloom Filter &#x111;&#x1EC3; check nh&#x1EEF;ng &#x1EE6;L &#x111;&#x1ED9;c h&#x1EA1;i. T&#x1EA5;t c&#x1EA3; URL &#x111;&#x1B0;&#x1EE3;c check &#x1EDF; Bloom Filter local tr&#x1B0;&#x1EDB;c khi &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i.</li></ul><h2 id="l%E1%BB%9Di-k%E1%BA%BFt">L&#x1EDD;i k&#x1EBF;t</h2><p>Bloom Filter &#x111;&#xE3; tr&#x1EDF; th&#xE0;nh m&#x1ED9;t c&#xF4;ng c&#x1EE5; m&#x1EA1;nh m&#x1EBD; trong x&#x1EED; l&#xFD; d&#x1EEF; li&#x1EC7;u v&#xE0; gi&#xFA;p gi&#x1EA3;i quy&#x1EBF;t nhi&#x1EC1;u v&#x1EA5;n &#x111;&#x1EC1; v&#x1EC1; hi&#x1EC7;u su&#x1EA5;t v&#xE0; b&#x1ED9; nh&#x1EDB; trong c&#xE1;c &#x1EE9;ng d&#x1EE5;ng th&#x1EF1;c t&#x1EBF;. C&#xE1;c c&#xF4;ng ty l&#x1EDB;n v&#xE0; t&#x1ED5; ch&#x1EE9;c tr&#xEA;n kh&#x1EAF;p th&#x1EBF; gi&#x1EDB;i &#x111;&#xE3; s&#x1EED; d&#x1EE5;ng Bloom Filter &#x111;&#x1EC3; c&#x1EA3;i thi&#x1EC7;n d&#x1ECB;ch v&#x1EE5; v&#xE0; t&#x1ED1;i &#x1B0;u h&#xF3;a x&#x1EED; l&#xFD; d&#x1EEF; li&#x1EC7;u c&#x1EE7;a h&#x1ECD;. Hy v&#x1ECD;ng qua b&#xE0;i vi&#x1EBF;t n&#xE0;y b&#x1EA1;n c&#xF3; th&#xEA;m c&#xF4;ng c&#x1EE5; &#x111;&#x1EC3; gi&#x1EA3;i quy&#x1EBF;t c&#xE1;c b&#xE0;i to&#xE1;n sau c&#x1EE7;a m&#xEC;nh. (Thay v&#xEC; HashMap =))</p><h5 id="references">References</h5>]]></content:encoded></item><item><title><![CDATA[Ansible Role]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://engineering.shopbase.com/content/images/2024/02/Ansible-la-gi.jpg" class="kg-image" alt loading="lazy" width="1024" height="512" srcset="https://engineering.shopbase.com/content/images/size/w600/2024/02/Ansible-la-gi.jpg 600w, https://engineering.shopbase.com/content/images/size/w1000/2024/02/Ansible-la-gi.jpg 1000w, https://engineering.shopbase.com/content/images/2024/02/Ansible-la-gi.jpg 1024w" sizes="(min-width: 720px) 720px"></figure><h2 id="gi%E1%BB%9Bi-thi%E1%BB%87u-v%E1%BB%81-ansible-role">Gi&#x1EDB;i thi&#x1EC7;u v&#x1EC1; Ansible Role</h2><p>M&#xF4; t&#x1EA3;: Ansible role cung c&#x1EA5;p 1 framework v&#xE0; c&#x1EA5;u tr&#xFA;c &#x111;&#x1EC3; thi&#x1EBF;t l&#x1EAD;p c&#xE1;c tasks, variables, handlers, metadata, templates, v&#xE0; c&#xE1;</p>]]></description><link>https://engineering.shopbase.com/ansible/</link><guid isPermaLink="false">65bb1d7e95b8649d9ab038c3</guid><dc:creator><![CDATA[Tung Trieu]]></dc:creator><pubDate>Thu, 01 Feb 2024 04:37:59 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/ansble.png" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://engineering.shopbase.com/content/images/2024/02/Ansible-la-gi.jpg" class="kg-image" alt="Ansible Role" loading="lazy" width="1024" height="512" srcset="https://engineering.shopbase.com/content/images/size/w600/2024/02/Ansible-la-gi.jpg 600w, https://engineering.shopbase.com/content/images/size/w1000/2024/02/Ansible-la-gi.jpg 1000w, https://engineering.shopbase.com/content/images/2024/02/Ansible-la-gi.jpg 1024w" sizes="(min-width: 720px) 720px"></figure><h2 id="gi%E1%BB%9Bi-thi%E1%BB%87u-v%E1%BB%81-ansible-role">Gi&#x1EDB;i thi&#x1EC7;u v&#x1EC1; Ansible Role</h2><img src="https://engineering.shopbase.com/content/images/2024/02/ansble.png" alt="Ansible Role"><p>M&#xF4; t&#x1EA3;: Ansible role cung c&#x1EA5;p 1 framework v&#xE0; c&#x1EA5;u tr&#xFA;c &#x111;&#x1EC3; thi&#x1EBF;t l&#x1EAD;p c&#xE1;c tasks, variables, handlers, metadata, templates, v&#xE0; c&#xE1;c files kh&#xE1;c. Ch&#xFA;ng cho ph&#xE9;p ta s&#x1EED; d&#x1EE5;ng l&#x1EA1;i v&#xE0; chia s&#x1EBB; Ansible code 1 c&#xE1;ch hi&#x1EC7;u qu&#x1EA3;.</p><p>B&#x1EB1;ng c&#xE1;ch n&#xE0;y, ch&#xFA;ng ta c&#xF3; th&#x1EC3; tham chi&#x1EBF;u v&#xE0; g&#x1ECD;i &#x111;&#x1EBF;n roles &#x1EDF; nhi&#x1EC1;u playbook v&#x1EDB;i ch&#x1EC9; 1 v&#xE0;i d&#xF2;ng code trong khi ch&#xFA;ng ta c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng l&#x1EA1;i c&#xF9;ng roles tr&#xEA;n nhi&#x1EC1;u projects m&#xE0; kh&#xF4;ng ph&#x1EA3;i l&#x1EB7;p &#x111;i l&#x1EB7;p l&#x1EA1;i code.</p><h2 id="hi%E1%BB%87u-qu%E1%BA%A3-c%E1%BB%A7a-roles-trong-ansible">Hi&#x1EC7;u qu&#x1EA3; c&#x1EE7;a Roles trong Ansible</h2><p>Khi b&#x1EAF;t &#x111;&#x1EA7;u v&#x1EDB;i Ansible, ch&#xFA;ng ta th&#x1B0;&#x1EDD;ng vi&#x1EBF;t nhi&#x1EC1;u playbook &#x111;&#x1EC3; t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a nhi&#x1EC1;u task m&#x1ED9;t c&#xE1;ch nhanh ch&#xF3;ng. Trong qu&#xE1; tr&#xEC;nh &#x111;&#xF3;, k&#x1EF9; n&#x103;ng c&#x1EE7;a ch&#xFA;ng ta s&#x1EBD; l&#xEA;n cao d&#x1EA7;n cho t&#x1EDB;i khi &#x111;&#x1EA1;t &#x111;&#x1EBF;n 1 gi&#x1EDB;i h&#x1EA1;n. V&#xE0; do &#x111;&#xF3;, Ansible roles l&#xE0; th&#x1EE9; &#x111;&#x1EC3; b&#x1EE9;c ph&#xE1; gi&#x1EDB;i h&#x1EA1;n n&#xE0;y.</p><p>T&#x1ED5; ch&#x1EE9;c Ansible content c&#x1EE7;a ch&#xFA;ng ta v&#xE0;o c&#xE1;c roles cung c&#x1EA5;p cho ch&#xFA;ng ta 1 c&#x1EA5;u tr&#xFA;c d&#x1EC5; d&#xE0;ng qu&#x1EA3;n l&#xFD; h&#x1A1;n nhi&#x1EC1;u so v&#x1EDB;i s&#x1EED; d&#x1EE5;ng playbooks. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; th&#x1EC3; kh&#xF4;ng qu&#xE1; r&#xF5; r&#xE0;ng trong nh&#x1EEF;ng d&#x1EF1; &#xE1;n nh&#x1ECF; nh&#x1B0;ng khi s&#x1ED1; l&#x1B0;&#x1EE3;ng playbook t&#x103;ng l&#xEA;n, &#x111;&#x1ED9; ph&#x1EE9;c t&#x1EA1;p qu&#x1EA3; d&#x1EF1; &#xE1;n c&#x169;ng theo &#x111;&#xF3; ph&#xE1;t tri&#x1EC3;n.</p><p>Cu&#x1ED1;i c&#xF9;ng, &#x111;&#x1EB7;t Ansible code v&#xE0;o nh&#x1EEF;ng roles cho ph&#xE9;p ta t&#x1ED5; ch&#x1EE9;c c&#xE1;c d&#x1EF1; &#xE1;n t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a c&#x1EE7;a m&#xEC;nh th&#xE0;nh c&#xE1;c nh&#xF3;m logic v&#xE0; tu&#xE2;n theo c&#xE1;c m&#x1ED1;i b&#x1EAD;n t&#xE2;m v&#x1EC1; nguy&#xEA;n t&#x1EAF;c thi&#x1EBF;t k&#x1EBF; ph&#xE2;n t&#xE1;ch. S&#x1EF1; ph&#x1ED1;i h&#x1EE3;p v&#xE0; t&#x1ED1;c &#x111;&#x1ED9; ph&#xE1;t tri&#x1EC3;n c&#x169;ng &#x111;&#x1B0;&#x1EE3;c c&#x1EA3;i thi&#x1EC7;n nhi&#x1EC1;u khi nh&#x1EEF;ng ng&#x1B0;&#x1EDD;i d&#xF9;ng kh&#xE1;c nhau c&#xF3; th&#x1EC3; l&#xE0;m vi&#x1EC7;c tr&#xEA;n nhi&#x1EC1;u roles ri&#xEA;ng bi&#x1EC7;t song song m&#xE0; kh&#xF4;ng ph&#x1EA3;i s&#x1EED;a &#x111;&#x1ED5;i chung 1 playbook.</p><h2 id="c%E1%BA%A5u-tr%C3%BAc-ansible-roles">C&#x1EA5;u tr&#xFA;c Ansible Roles</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://engineering.shopbase.com/content/images/2024/02/image.png" class="kg-image" alt="Ansible Role" loading="lazy" width="676" height="338" srcset="https://engineering.shopbase.com/content/images/size/w600/2024/02/image.png 600w, https://engineering.shopbase.com/content/images/2024/02/image.png 676w"><figcaption><a href="https://www.slideshare.net/IvanSerdyuk/introduction-to-ansible-galaxy?ref=engineering.shopbase.com"><span style="white-space: pre-wrap;">Role structure</span></a></figcaption></figure><p>Ansible s&#x1EBD; ki&#x1EC3;m tra c&#xE1;c file main.yml, c&#xE1;c bi&#x1EBF;n trong vars, v&#xE0; n&#x1ED9;i dung li&#xEA;n quan trong m&#x1ED7;i &#x111;&#x1B0;&#x1EDD;ng d&#x1EAB;n con. Vi&#x1EC7;c th&#xEA;m v&#xE0;o nh&#x1EEF;ng file YAML trong 1 v&#xE0;i &#x111;&#x1B0;&#x1EDD;ng d&#x1EAB;n l&#xE0; ho&#xE0;n to&#xE0;n c&#xF3; th&#x1EC3;. V&#xED; d&#x1EE5;y, b&#x1EA1;n c&#xF3; th&#x1EC3; nh&#xF3;m c&#xE1;c tasks c&#x1EE7;a b&#x1EA1;n trong nh&#x1EEF;ng file YAML ri&#xEA;ng bi&#x1EC7;t t&#xF9;y theo 1 v&#xE0;i &#x111;&#x1EB7;c t&#xED;nh:</p><ul><li><strong>defaults</strong>: Bao g&#x1ED3;m c&#xE1;c gi&#xE1; tr&#x1ECB; m&#x1EB7;c &#x111;&#x1ECB;nh cho c&#xE1;c bi&#x1EBF;n c&#x1EE7;a role. &#x1EDE; &#x111;&#xE2;y ch&#xFA;ng ta &#x111;&#x1ECB;nh ngh&#x129;a 1 v&#xE0;i bi&#x1EBF;n m&#x1EB7;c &#x111;&#x1ECB;nh, nh&#x1B0;ng ch&#xFA;ng c&#xF3; &#x111;&#x1ED9; &#x1B0;u ti&#xEA;n th&#x1EA5;p nh&#x1EA5;t v&#xE0; c&#x169;ng th&#x1B0;&#x1EDD;ng b&#x1ECB; ghi &#x111;&#xE8; b&#x1EDF;i c&#xE1;c ph&#x1B0;&#x1A1;ng th&#x1EE9;c kh&#xE1;c &#x111;&#x1EC3; customzie role.</li><li><strong>files</strong>: Ch&#x1EE9;a c&#xE1;c file t&#x129;nh v&#xE0; custom m&#xE0; role s&#x1EED; d&#x1EE5;ng &#x111;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n m&#x1ED9;t v&#xE0;i tasks nh&#x1EA5;t &#x111;&#x1ECB;nh.</li><li><strong>handlers</strong>: 1 t&#x1EAD;p h&#x1EE3;p c&#xE1;c handlers m&#xE0; c&#xF3; th&#x1EC3; k&#xED;ch ho&#x1EA1;t b&#x1EDF;i c&#xE1;c tasks c&#x1EE7;a role.</li><li><strong>meta</strong>: Bao g&#x1ED3;m th&#xF4;ng tin metadata cho role, n&#xF3; c&#xF3; th&#x1EC3; l&#xE0; c&#xE1;c dependencies (ph&#x1EE5; thu&#x1ED9;c), t&#xE1;c gi&#x1EA3;, license, n&#x1EC1;n t&#x1EA3;ng kh&#x1EA3; d&#x1EE5;ng,&#x2026;</li><li><strong>tasks</strong>: 1 danh s&#xE1;ch c&#xE1;c tasks &#x111;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n b&#x1EDF;i role. Ph&#x1EA7;n n&#xE0;y c&#xF3; th&#x1EC3; hi&#x1EC3;u t&#x1B0;&#x1A1;ng t&#x1EF1; nh&#x1B0; task section trong 1 playbook.</li><li><strong>templates</strong>: Bao g&#x1ED3;m c&#xE1;c file template Jinja2 s&#x1EED; d&#x1EE5;ng b&#x1EDF;i c&#xE1;c tasks c&#x1EE7;a role.</li><li><strong>tests</strong>: Bao g&#x1ED3;m c&#xE1;c file c&#x1EA5;u h&#xEC;nh li&#xEA;n quan &#x111;&#x1EBF;n ki&#x1EC3;m th&#x1EED; role.</li><li><strong>vars</strong>: Ch&#x1EE9;a c&#xE1;c bi&#x1EBF;n &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1ECB;nh ngh&#x129;a cho role (c&#xE1;c bi&#x1EBF;n &#x1EDF; &#x111;&#xE2;y c&#xF3; &#x111;&#x1ED9; &#x1B0;u ti&#xEA;n cao h&#x1A1;n&#xA0;<strong>defaults</strong>).</li></ul><h2 id="h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-c%C3%A0i-%C4%91%E1%BA%B7t-s%E1%BB%AD-d%E1%BB%A5ng-ansile-role">H&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE0;i &#x111;&#x1EB7;t, s&#x1EED; d&#x1EE5;ng Ansile Role</h2><ol><li>C&#xE0;i &#x111;&#x1EB7;t Ansible</li></ol><ul><li>Link h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE0;i &#x111;&#x1EB7;t: <a href="https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html?ref=engineering.shopbase.com">https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html</a></li></ul><ol start="2"><li>S&#x1EED; d&#x1EE5;ng ansible role</li></ol><ul><li>K&#x1ECB;ch b&#x1EA3;n: S&#x1EED; d&#x1EE5;ng ansible role &#x111;&#x1EC3; &#x111;&#x1EA9;y 1 file bash bash-hello.sh l&#xEA;n server v&#xE0; ch&#x1EA1;y bash &#x111;&#x1EC3; in d&#xF2;ng ch&#x1EEF; &quot;Hello World&quot; ra m&#xE0;n h&#xEC;nh.</li><li>C&#x1EA5;u tr&#xFA;c c&#x1EE7;a Ansible role Test</li></ul><figure class="kg-card kg-image-card"><img src="https://engineering.shopbase.com/content/images/2024/02/image-1.png" class="kg-image" alt="Ansible Role" loading="lazy" width="777" height="278" srcset="https://engineering.shopbase.com/content/images/size/w600/2024/02/image-1.png 600w, https://engineering.shopbase.com/content/images/2024/02/image-1.png 777w" sizes="(min-width: 720px) 720px"></figure><ul><li>N&#x1ED9;i dung file main.yml</li></ul><figure class="kg-card kg-image-card"><img src="https://engineering.shopbase.com/content/images/2024/02/image-3.png" class="kg-image" alt="Ansible Role" loading="lazy" width="731" height="417" srcset="https://engineering.shopbase.com/content/images/size/w600/2024/02/image-3.png 600w, https://engineering.shopbase.com/content/images/2024/02/image-3.png 731w" sizes="(min-width: 720px) 720px"></figure><ul><li>Ch&#x1EA1;y l&#x1EC7;nh v&#xE0; hi&#x1EC7;n th&#x1ECB; k&#x1EBF;t qu&#x1EA3; ra m&#xE0;n h&#xEC;nh</li></ul><p>Command: &quot;<em>ansible-playbook -i ansible_hosts playbook.yml</em>&quot;</p><figure class="kg-card kg-image-card"><img src="https://engineering.shopbase.com/content/images/2024/02/image-4.png" class="kg-image" alt="Ansible Role" loading="lazy" width="1911" height="565" srcset="https://engineering.shopbase.com/content/images/size/w600/2024/02/image-4.png 600w, https://engineering.shopbase.com/content/images/size/w1000/2024/02/image-4.png 1000w, https://engineering.shopbase.com/content/images/size/w1600/2024/02/image-4.png 1600w, https://engineering.shopbase.com/content/images/2024/02/image-4.png 1911w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[Coding Challenge #1]]></title><description><![CDATA[<h1 id="b%C3%A0i-to%C3%A1n-rate-limiter-advanced-version">B&#xE0;i to&#xE1;n Rate Limiter: Advanced Version</h1><p>Rate Limiter l&#xE0; m&#x1ED9;t b&#xE0;i to&#xE1;n c&#x1A1; b&#x1EA3;n, ph&#x1ED5; bi&#x1EBF;n trong thi&#x1EBF;t k&#x1EBF; h&#x1EC7; th&#x1ED1;ng nh&#x1EB1;m ki&#x1EC3;m</p>]]></description><link>https://engineering.shopbase.com/coding-challenge-1/</link><guid isPermaLink="false">65bb3be595b8649d9ab03b6f</guid><category><![CDATA[coding-challenge]]></category><category><![CDATA[rate-limit]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Tue, 30 Jan 2024 06:37:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1517697063925-d82f8da41135?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHJhdGUlMjBsaW1pdHxlbnwwfHx8fDE3MDY3Njk0OTF8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h1 id="b%C3%A0i-to%C3%A1n-rate-limiter-advanced-version">B&#xE0;i to&#xE1;n Rate Limiter: Advanced Version</h1><img src="https://images.unsplash.com/photo-1517697063925-d82f8da41135?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHJhdGUlMjBsaW1pdHxlbnwwfHx8fDE3MDY3Njk0OTF8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Coding Challenge #1"><p>Rate Limiter l&#xE0; m&#x1ED9;t b&#xE0;i to&#xE1;n c&#x1A1; b&#x1EA3;n, ph&#x1ED5; bi&#x1EBF;n trong thi&#x1EBF;t k&#x1EBF; h&#x1EC7; th&#x1ED1;ng nh&#x1EB1;m ki&#x1EC3;m so&#xE1;t s&#x1ED1; l&#x1B0;&#x1EE3;ng requests &#x111;&#x1B0;&#x1EE3;c th&#x1EF1;c hi&#x1EC7;n trong m&#x1ED9;t kho&#x1EA3;ng th&#x1EDD;i gian nh&#x1EA5;t &#x111;&#x1ECB;nh, gi&#xFA;p cho h&#x1EC7; th&#x1ED1;ng kh&#xF4;ng b&#x1ECB; qu&#xE1; t&#x1EA3;i m&#x1ED9;t c&#xE1;ch &#x111;&#x1ED9;t bi&#x1EBF;n. OCG c&#x169;ng &#x111;&#xE3; implement m&#x1ED9;t c&#x1A1; ch&#x1EBF; Rate Limit &#x1EDF; t&#x1EA7;ng OpenResty cho ShopBase. B&#x1EA1;n h&#xE3;y thi&#x1EBF;t k&#x1EBF; v&#xE0; implement m&#x1ED9;t c&#x1A1; ch&#x1EBF; Rate limit v&#x1EDB;i m&#x1ED9;t s&#x1ED1; requirements sau:</p><h1 id="background">Background</h1><p>Storefront c&#x1EE7;a c&#xE1;c stores tr&#xEA;n ShopBase r&#x1EA5;t hay b&#x1ECB; crawl b&#x1EDF;i nhi&#x1EC1;u th&#x1EC3; lo&#x1EA1;i bot nh&#x1B0;: Known bots (Google bot, Facebook bot, Bing bot)&#x2026;hay c&#xE1;c unkown bots (c&#xE1;c bots nhi&#x1EC1;u b&#xEA;n b&#xEA;n t&#x1EF1; implement &#x111;&#x1EC3; crawl d&#x1EEF; li&#x1EC7;u). Th&#xF4;ng th&#x1B0;&#x1EDD;ng, c&#xE1;c known bot s&#x1EBD; crawl theo nh&#x1EEF;ng quy t&#x1EAF;c nh&#x1EA5;t &#x111;&#x1ECB;nh nh&#x1B0;:&#xA0;</p><ul><li>T&#xF4;n tr&#x1ECD;ng th&#xF4;ng tin trong file robots.txt</li><li>Khi crawl th&#xEC; th&#x1B0;&#x1EDD;ng theo d&#xF5;i c&#xE1;c HTTP Rate Limit header hay code HTTP 429 &#x111;&#x1EC3; &#x111;i&#x1EC1;u ch&#x1EC9;nh qu&#xE1; tr&#xEC;nh crawl c&#x1EE7;a m&#xEC;nh</li></ul><p>Tuy v&#x1EAD;y, c&#xE1;c unknown bots l&#x1EA1;i kh&#xF4;ng l&#xE0;m v&#x1EAD;y d&#x1EAB;n &#x111;&#x1EBF;n h&#x1EC7; th&#x1ED1;ng c&#xF3; th&#x1EC3; s&#x1EAD;p do handle qu&#xE1; nhi&#x1EC1;u requests.&#xA0;</p><h1 id="requirements">Requirements</h1><ul><li>T&#xED;nh n&#x103;ng c&#x1A1; b&#x1EA3;n:&#xA0;<ul><li>X&#xE2;y d&#x1EF1;ng m&#x1ED9;t Rate Limiter c&#xF3; <strong>kh&#x1EA3; n&#x103;ng ki&#x1EC3;m so&#xE1;t</strong> s&#x1ED1; l&#x1B0;&#x1EE3;ng requests d&#x1EF1;a tr&#xEA;n m&#x1ED9;t s&#x1ED1; ti&#xEA;u ch&#xED; nh&#x1EA5;t &#x111;&#x1ECB;nh, ch&#x1EB3;ng h&#x1EA1;n nh&#x1B0; s&#x1ED1; l&#x1B0;&#x1EE3;ng requests m&#x1ED7;i gi&#xE2;y, m&#x1ED7;i ph&#xFA;t v&#xE0; m&#x1ED7;i ng&#xE0;y cho t&#x1EEB;ng domain v&#xE0; IP ngu&#x1ED3;n.<ul><li>&#x110;&#x1A1;n v&#x1ECB; th&#x1EDD;i gian t&#xED;nh to&#xE1;n l&#x1B0;&#x1EE3;ng request c&#xF3; th&#x1EC3; l&#xE0; 1s, 10s, 60s&#x2026;</li></ul></li><li>Ph&#xE2;n lo&#x1EA1;i &#x111;&#x1B0;&#x1EE3;c requests: H&#x1ED7; tr&#x1EE3; vi&#x1EC7;c ph&#xE2;n lo&#x1EA1;i requests theo lo&#x1EA1;i, v&#xED; d&#x1EE5;: user-based rate limiting v&#xE0; API endpoint-based rate limiting.<ul><li>User-based c&#xF3; th&#x1EC3; l&#xE0; theo IP ho&#x1EB7;c theo bot name, ho&#x1EB7;c 1 identity n&#xE0;o &#x111;&#xF3; truy c&#x1EAD;p v&#xE0;o h&#x1EC7; th&#x1ED1;ng.</li><li>API endpoint-based t&#x1EE9;c l&#xE0; c&#xF3; th&#x1EC3; set rate limit cho t&#x1EEB;ng endpoint API d&#x1EF1;a tr&#xEA;n IP ho&#x1EB7;c user.<ul><li>VD:&#xA0;<ul><li>API login ch&#x1EC9; &#x111;&#x1B0;&#x1EE3;c access v&#x1EDB;i limit 1 req/s/domain/ip</li><li>API get product c&#xF3; limit 100 req/s/domain/bot_name</li></ul></li></ul></li></ul></li><li>Thi&#x1EBF;t k&#x1EBF; m&#x1EDF; r&#x1ED9;ng: Thi&#x1EBF;t k&#x1EBF; h&#x1EC7; th&#x1ED1;ng sao cho n&#xF3; c&#xF3; kh&#x1EA3; n&#x103;ng m&#x1EDF; r&#x1ED9;ng d&#x1EC5; d&#xE0;ng theo chi&#x1EC1;u ngang (nhi&#x1EC1;u m&#xE1;y c&#xF9;ng c&#xF3; th&#x1EC3; ch&#x1EA1;y rate limit)</li><li>Qu&#x1EA3;n l&#xFD; tr&#x1EA1;ng th&#xE1;i v&#xE0; logs: Ghi log cho m&#x1ED7;i request b&#x1ECB; t&#x1EEB; ch&#x1ED1;i v&#xE0; duy tr&#xEC; th&#xF4;ng tin v&#x1EC1; tr&#x1EA1;ng th&#xE1;i c&#x1EE7;a Rate Limiter.<ul><li>V&#xED; d&#x1EE5;: l&#xFA;c &#x111;&#xF3;, IP/user &#x111;&#xE3; request bao nhi&#xEA;u req trong 1 kho&#x1EA3;ng th&#x1EDD;i gian r&#x1ED3;i, v&#xEC; sao b&#x1ECB; ch&#x1EB7;n truy c&#x1EAD;p</li></ul></li><li>Code clean: Implement &#x111;&#x1B0;&#x1EE3;c codebase 1 c&#xE1;ch clean nh&#x1EA5;t c&#xF3; th&#x1EC3; v&#xE0; &#xE1;p d&#x1EE5;ng &#x111;&#x1B0;&#x1EE3;c c&#xE1;c design pattern c&#x1EA7;n thi&#x1EBF;t v&#xE0;o codebase.</li></ul></li><li><strong><em><u>Ch&#xFA; &#xFD;</u>:</em></strong><ul><li>C&#x1EA7;n quy&#x1EBF;t &#x111;&#x1ECB;nh ki&#x1EC3;u support &#x111;&#x1A1;n v&#x1ECB; th&#x1EDD;i gian &#x111;&#x1EC3; thay &#x111;&#x1ED5;i &#x111;&#x1B0;&#x1EE3;c 1 c&#xE1;ch h&#x1EE3;p l&#xFD;.<ul><li>V&#xED; d&#x1EE5; &#x111;o theo 1s, 10s, 60s&#x2026;</li></ul></li><li>M&#x1ED7;i stores c&#xF3; th&#x1EC3; c&#xF3; nhi&#x1EC1;u domains, n&#xEA;n &#x111;&#x1A1;n v&#x1ECB; &#x111;&#x1EC3; ki&#x1EC3;m so&#xE1;t truy c&#x1EAD;p/limit l&#xE0; domain.&#xA0;<ul><li>V&#xED; d&#x1EE5;:<ul><li>C&#xF3; th&#x1EC3; set 20 requests/second/domain/src IP,&#xA0; 400 requests/minute/domain/src IP&#x2026;</li></ul></li></ul></li><li>N&#xEA;n c&#xF3; 1 hard limit cho to&#xE0;n b&#x1ED9; h&#x1EC7; th&#x1ED1;ng.<ul><li>V&#xED; d&#x1EE5;:<ul><li>Khi t&#x1ED5;ng traffic v&#xE0;o h&#x1EC7; th&#x1ED1;ng v&#x1B0;&#x1EE3;t qu&#xE1; ng&#x1B0;&#x1EE1;ng 10000 request/s &#x2192; c&#xE1;c request sau &#x111;&#xF3; s&#x1EBD; b&#x1ECB; rate limited</li></ul></li></ul></li></ul></li></ul><h2 id="g%E1%BB%A3i-%C3%BD"><strong>G&#x1EE3;i &#xFD;</strong></h2><ul><li>&#x110;&#x1EC3; x&#x1EED; l&#xFD; &#x111;&#x1B0;&#x1EE3;c b&#xE0;i to&#xE1;n n&#xE0;y, b&#x1EA1;n c&#x1EA7;n t&#xEC;m hi&#x1EC3;u c&#xE1;c thu&#x1EAD;t to&#xE1;n rate limiter v&#xE0; ch&#x1ECD;n ra m&#x1ED9;t thu&#x1EAD;t to&#xE1;n &#x111;&#x1EC3; c&#xF3; th&#x1EC3; implements 1 c&#xE1;ch &#x111;&#x1A1;n gi&#x1EA3;n nh&#x1EA5;t.<ul><li>N&#x1EBF;u b&#x1EA1;n mu&#x1ED1;n thu&#x1EAD;t to&#xE1;n kh&#xF3; h&#x1A1;n ho&#x1EB7;c c&#x1EA3;i ti&#x1EBF;n c&#xE1;c thu&#x1EAD;t to&#xE1;n &#x111;ang c&#xF3;, h&#xE3;y c&#x1EE9; l&#xE0;m theo c&#xE1;ch c&#x1EE7;a b&#x1EA1;n</li></ul></li><li>&#x110;&#xE2;y l&#xE0; m&#x1ED9;t b&#xE0;i to&#xE1;n v&#x1EC1; hi&#x1EC7;u n&#x103;ng n&#xEA;n b&#x1EA1;n <strong><em>n&#xEA;n </em></strong>vi&#x1EBF;t s&#x1EB5;n c&#xE1;c test cases, user stories &#x111;&#x1EC3; khi thi&#x1EBF;t k&#x1EBF;/code kh&#xF4;ng b&#x1ECB; thi&#x1EBF;u case n&#xE0;o<ul><li>C&#x1EA7;n c&#xF3; code/script test performance &#x111;&#x1EC3; b&#x1EA1;n c&#xF3; th&#x1EC3; t&#x1EF1; test &#x111;&#x1B0;&#x1EE3;c. V&#xED; d&#x1EE5; go test, wrk, apache bench, playwright&#x2026;</li></ul></li><li>B&#x1EA1;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng Golang ho&#x1EB7;c Nodejs (prefer Golang) &#x111;&#x1EC3; th&#x1EF1;c h&#xE0;nh</li><li>N&#xEA;n c&#xF3; thi&#x1EBF;t k&#x1EBF; h&#x1EC7; th&#x1ED1;ng r&#xF5; r&#xE0;ng tr&#x1B0;&#x1EDB;c khi b&#x1EAF;t tay v&#xE0;o code<ul><li>N&#x1EBF;u ch&#x1B0;a ch&#x1EAF;c ch&#x1EAF;n, b&#x1EA1;n h&#xE3;y check v&#x1EDB;i Lead ho&#x1EB7;c @TruongBui</li></ul></li></ul><h1 id="output">Output</h1><ol><li>1 b&#x1EA3;n thi&#x1EBF;t k&#x1EBF; h&#x1EC7; th&#x1ED1;ng bao g&#x1ED3;m:<ol><li>Tech docs theo <a href="https://docs.ocg.to/books/shopbase-tech-system/page/feature-name-techdocs-template/15549?ref=engineering.shopbase.com"><u>format c&#x1EE7;a OCG</u></a><ol><li>Gi&#x1EA3;i th&#xED;ch &#x111;&#x1B0;&#x1EE3;c r&#xF5; r&#xE0;ng thi&#x1EBF;t k&#x1EBF; c&#x1EE7;a b&#x1EA1;n trong &#x111;&#xF3;</li></ol></li></ol></li><li>1 user stories docs m&#xF4; t&#x1EA3; c&#xE1;c user stories b&#x1EA1;n s&#x1EBD; gi&#x1EA3;i quy&#x1EBF;t. C&#xF3; th&#x1EC3; theo format t&#x1EA1;i <a href="https://docs.google.com/spreadsheets/d/1_nen8veef83ZRu2zNvfn0oWl0Mm4nssBhKUEkpFY9fM/edit?ref=engineering.shopbase.com#gid=1055385780"><u>&#x111;&#xE2;y</u></a></li><li>Codebase trong gitlab c&#x1EE7;a c&#xF4;ng ty, &#x111;&#x1EB7;t trong t&#xE0;i kho&#x1EA3;n c&#x1EE7;a b&#x1EA1;n<ol><li>gitlab.shopbase.com/<em>user_name</em>/<em>challenge_1</em><ol><li>Code base bao g&#x1ED3;m code implement ch&#x1EE9;c n&#x103;ng n&#xE0;y v&#xE0; 1 HTTP server demo</li><li>Th&#xF4;ng tin &#x111;o &#x111;&#x1EA1;c performance h&#x1EC7; th&#x1ED1;ng l&#xFA;c c&#xF3; v&#xE0; kh&#xF4;ng &#xE1;p d&#x1EE5;ng rate limiter</li><li>1 file README.md c&#xF3; c&#xE1;c th&#xF4;ng tin v&#x1EC1; nh&#x1EEF;ng highlight c&#x1EE7;a b&#x1EA1;n v&#x1EC1; thi&#x1EBF;t k&#x1EBF;, codebase</li><li>Unit &amp; Integration test<ol><li>Test Coverage &gt; 60%</li><li>C&#xF3; code/script ch&#x1EA1;y test<ol><li>Xem h&#x1EC7; th&#x1ED1;ng c&#xF3; ch&#x1EA1;y &#x111;&#xFA;ng rate limit theo config kh&#xF4;ng</li></ol></li></ol></li></ol></li></ol></li></ol><h1 id="th%E1%BB%9Di-h%E1%BA%A1n-ho%C3%A0n-th%C3%A0nh">Th&#x1EDD;i h&#x1EA1;n ho&#xE0;n th&#xE0;nh</h1><p>H&#x1EBF;t ng&#xE0;y 18/2/2024</p><h1 id="questions">Questions</h1><p>N&#x1EBF;u c&#xF3; c&#xE2;u h&#x1ECF;i, h&#xE3;y &#x111;&#x1EEB;ng ng&#x1EA7;n ng&#x1EA1;i chat v&#xE0;o channel #dev &#x111;&#x1EC3; &#x111;&#x1B0;&#x1EE3;c gi&#x1EA3;i &#x111;&#xE1;p</p><h1 id="reference">Reference</h1><p><a href="https://drive.google.com/file/d/17x4Q4HsRLNYTUkmwW0trBKCbOqORg8Sd/view?ref=engineering.shopbase.com">System Design Interview Volume 1</a> - Alex Xu</p>]]></content:encoded></item><item><title><![CDATA[LocalStack - AWS Cloud trên máy tính của bạn]]></title><description><![CDATA[LocalStack giúp bạn giả lập hơn 80 dịch vụ AWS trên máy tính của bạn, cho phép bạn phát triển và kiểm tra ứng dụng AWS của mình một cách nhanh chóng.]]></description><link>https://engineering.shopbase.com/localstack/</link><guid isPermaLink="false">65bb0e9c95b8649d9ab036cb</guid><category><![CDATA[localstack]]></category><category><![CDATA[aws]]></category><dc:creator><![CDATA[Phan Khanh]]></dc:creator><pubDate>Tue, 30 Jan 2024 03:35:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/localstack-readme-banner.svg" medium="image"/><content:encoded><![CDATA[<h3 id="gi%E1%BB%9Bi-thi%E1%BB%87u-v%E1%BB%81-localstack">Gi&#x1EDB;i thi&#x1EC7;u v&#x1EC1; LocalStack</h3><img src="https://engineering.shopbase.com/content/images/2024/02/localstack-readme-banner.svg" alt="LocalStack - AWS Cloud tr&#xEA;n m&#xE1;y t&#xED;nh c&#x1EE7;a b&#x1EA1;n"><p><a href="https://github.com/localstack/localstack?ref=engineering.shopbase.com" rel="noreferrer">LocalStack</a> l&#xE0; m&#x1ED9;t framework m&#xE3; ngu&#x1ED3;n m&#x1EDF;, cho ph&#xE9;p b&#x1EA1;n gi&#x1EA3; l&#x1EAD;p h&#x1A1;n 80 d&#x1ECB;ch v&#x1EE5; AWS tr&#xEA;n local. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p vi&#x1EC7;c ph&#xE1;t tri&#x1EC3;n v&#xE0; ki&#x1EC3;m th&#x1EED; &#x1EE9;ng d&#x1EE5;ng tr&#x1EDF; n&#xEA;n d&#x1EC5; d&#xE0;ng h&#x1A1;n, m&#xE0; kh&#xF4;ng c&#x1EA7;n c&#xF3; t&#xE0;i kho&#x1EA3;n AWS.</p><p><em>Tuy nhi&#xEA;n, m&#x1ED9;t s&#x1ED1; d&#x1ECB;ch v&#x1EE5; y&#xEA;u c&#x1EA7;u phi&#xEA;n b&#x1EA3;n tr&#x1EA3; ph&#xED; LocalStack Pro &#x111;&#x1EC3; s&#x1EED; d&#x1EE5;ng</em>&#x1F643;</p><h3 id="c%C3%A1c-%C4%91i%E1%BB%83m-n%E1%BB%95i-b%E1%BA%ADt-c%E1%BB%A7a-localstack">C&#xE1;c &#x111;i&#x1EC3;m n&#x1ED5;i b&#x1EAD;t c&#x1EE7;a LocalStack</h3><ol><li><strong>Gi&#x1EA3; l&#x1EAD;p h&#x1A1;n 80 d&#x1ECB;ch v&#x1EE5; AWS</strong><br>LocalStack h&#x1ED7; tr&#x1EE3; m&#xF4; ph&#x1ECF;ng c&#xE1;c d&#x1ECB;ch v&#x1EE5; AWS quan tr&#x1ECD;ng nh&#x1B0; S3, Lambda, RDS, SQS, SNN v&#xE0; nhi&#x1EC1;u d&#x1ECB;ch v&#x1EE5; kh&#xE1;c. B&#x1EA1;n c&#xF3; th&#x1EC3; xem v&#xE0; t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i c&#xE1;c t&#xE0;i nguy&#xEA;n n&#xE0;y nh&#x1B0; l&#xE0; khi s&#x1EED; d&#x1EE5;ng c&#xE1;c d&#x1ECB;ch v&#x1EE5; th&#x1EF1;c t&#x1EBF; t&#x1EEB; AWS. &#x110;i&#x1EC1;u n&#xE0;y r&#x1EA5;t h&#x1EEF;u &#xED;ch trong qu&#xE1; tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n v&#xE0; ki&#x1EC3;m th&#x1EED; &#x1EE9;ng d&#x1EE5;ng, v&#xEC; b&#x1EA1;n c&#xF3; th&#x1EC3; l&#xE0;m vi&#x1EC7;c c&#x1EE5;c b&#x1ED9; m&#xE0; kh&#xF4;ng c&#x1EA7;n t&#xE0;i kho&#x1EA3;n AWS v&#xE0; t&#x1EA5;t nhi&#xEA;n l&#xE0; c&#x1EA3; internet.</li><li><strong>D&#x1EC5; d&#xE0;ng c&#xE0;i &#x111;&#x1EB7;t v&#xE0; s&#x1EED; d&#x1EE5;ng</strong><br>LocalStack &#x111;&#x1B0;&#x1EE3;c vi&#x1EBF;t b&#x1EB1;ng Python v&#xE0; c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c c&#xE0;i &#x111;&#x1EB7;t th&#xF4;ng qua pip. Sau khi c&#xE0;i &#x111;&#x1EB7;t, b&#x1EA1;n c&#xF3; th&#x1EC3; ch&#x1EA1;y LocalStack b&#x1EB1;ng m&#x1ED9;t d&#xF2;ng l&#x1EC7;nh duy nh&#x1EA5;t. N&#xF3; cung c&#x1EA5;p c&#x1EA3; giao di&#x1EC7;n web UI v&#xE0; c&#xE1;c API &#x111;&#x1EC3; t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i c&#xE1;c d&#x1ECB;ch v&#x1EE5;.</li><li><strong>C&#x1EA5;u h&#xEC;nh linh ho&#x1EA1;t</strong><br>LocalStack cho ph&#xE9;p b&#x1EA1;n c&#x1EA5;u h&#xEC;nh nhi&#x1EC1;u thu&#x1ED9;c t&#xED;nh kh&#xE1;c nhau, ch&#x1EB3;ng h&#x1EA1;n nh&#x1B0; port c&#x1EE7;a t&#x1EEB;ng d&#x1ECB;ch v&#x1EE5;, th&#xF4;ng tin &#x111;&#x103;ng nh&#x1EAD;p, quy&#x1EC1;n truy c&#x1EAD;p v&#xE0; nhi&#x1EC1;u h&#x1A1;n n&#x1EEF;a. B&#x1EA1;n c&#xF3; th&#x1EC3; t&#xF9;y ch&#x1EC9;nh vi&#x1EC7;c &#x111;&#x1EC3; ph&#xF9; h&#x1EE3;p v&#x1EDB;i y&#xEA;u c&#x1EA7;u c&#x1EE7;a c&#x1EE7;a b&#x1EA1;n.</li></ol><h3 id="h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-setup-localstack">H&#x1B0;&#x1EDB;ng d&#x1EAB;n setup LocalStack</h3><p>LocalStack h&#x1ED7; tr&#x1EE3; nhi&#x1EC1;u h&#x1EC7; &#x111;i&#x1EC1;u h&#xE0;nh v&#xE0; nhi&#x1EC1;u ph&#x1B0;&#x1A1;ng th&#x1EE9;c &#x111;&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t v&#xE0; s&#x1EED; d&#x1EE5;ng nh&#x1B0; nh&#x1B0;ng &#x1EDF; &#x111;&#xE2;y t&#xF4;i s&#x1EBD; h&#x1B0;&#x1EDB;ng d&#x1EAB;n setup localstack tr&#xEA;n Ubuntu v&#x1EDB;i pip:<br>1. C&#xE0;i &#x111;&#x1EB7;t LocalStack b&#x1EB1;ng pip</p><pre><code class="language-bash">pip install localstask</code></pre><ol start="2"><li>Sau khi c&#xE0;i &#x111;&#x1EB7;t th&#xE0;nh c&#xF4;ng, b&#x1EA1;n c&#xF3; th&#x1EC3; ch&#x1EA1;y LocalStack b&#x1EB1;ng c&#xE1;ch ch&#x1EA1;y l&#x1EC7;nh</li></ol><pre><code class="language-bash">localstask start</code></pre><p>m&#xE0;n h&#xEC;nh hi&#x1EC7;n ra nh&#x1B0; sau l&#xE0; &#x111;&#xE3; start th&#xE0;nh c&#xF4;ng</p><pre><code class="language-text">     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,&lt;
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 &#x1F4BB; LocalStack CLI 3.1.0
 &#x1F464; Profile: default

[11:09:15] starting LocalStack in Docker mode &#x1F433;  
&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500; LocalStack Runtime Log (press CTRL-C to quit) &#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;
LocalStack version: 3.0.3.dev
LocalStack Docker container id: 06bb3bfac191
LocalStack build date: 2024-01-19
LocalStack build git hash: fd8b8ace

2024-02-01T04:09:17.982  INFO --- [-functhread4] hypercorn.error            : Running on https://0.0.0.0:4566 (CTRL + C to quit)
2024-02-01T04:09:17.982  INFO --- [-functhread4] hypercorn.error            : Running on https://0.0.0.0:4566 (CTRL + C to quit)
Ready.</code></pre><h3 id="k%E1%BA%BFt-n%E1%BB%91i-v%E1%BB%9Bi-localstack">K&#x1EBF;t n&#x1ED1;i v&#x1EDB;i LocalStack</h3><p>Ch&#xFA;ng ta th&#x1B0;&#x1EDD;ng thao t&#xE1;c v&#x1EDB;i c&#xE1;c d&#x1ECB;ch v&#x1EE5; AWS th&#xF4;ng qua AWS CLI ho&#x1EB7;c t&#x1EEB; &#x1EE9;ng d&#x1EE5;ng th&#xF4;ng qua AWS SDK.</p><p>AWS CLI v&#xE0; AWS SDK &#x111;&#x1EC1;u h&#x1ED7; tr&#x1EE3; ghi &#x111;&#xE8; endpoint c&#x1EE7;a AWS. &#x110;&#x1EC3; thao t&#xE1;c v&#x1EDB;i LocalStack th&#xF4;ng qua AWS CLI ch&#xFA;ng ta ch&#x1EC9; c&#x1EA7;n th&#xEA;m param <code>--endpointurl http://localhost:4566</code>.</p><p>&#x110;&#x1EC3; thao t&#xE1;c v&#x1EDB;i LocalStack, ch&#xFA;ng ta n&#xEA;n c&#xE0;i th&#xEA;m <code>awslocal</code> &#x111;&#x1EC3; thu&#x1EAD;n ti&#x1EC7;n h&#x1A1;n cho vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng:</p><pre><code class="language-bash">pip install awscli-local</code></pre><h3 id="v%C3%AD-d%E1%BB%A5-t%C6%B0%C6%A1ng-t%C3%A1c-v%E1%BB%9Bi-localstack">V&#xED; d&#x1EE5; t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i LocalStack</h3><figure class="kg-card kg-code-card"><pre><code class="language-bash">awslocal s3api create-bucket --bucket sample-bucket --region us-west-2</code></pre><figcaption><p><span style="white-space: pre-wrap;">Create bucket</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-bash">awslocal s3api list-buckets</code></pre><figcaption><p><span style="white-space: pre-wrap;">List bucket</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-bash">awslocal s3api put-object \
  --bucket sample-bucket \
  --key image.jpg \
  --body image.jpg \
  --region us-west-2</code></pre><figcaption><p><span style="white-space: pre-wrap;">Put object</span></p></figcaption></figure><p>N&#x1EBF;u mu&#x1ED1;n s&#x1EED; d&#x1EE5;ng UI th&#xEC; c&#xE1;c b&#x1EA1;n c&#x1EA7;n c&#xF3; t&#xE0;i kho&#x1EA3;n <a href="https://app.localstack.cloud/?ref=engineering.shopbase.com">Localstack</a> &#x111;&#x1EC3; truy c&#x1EAD;p, b&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o th&#xEA;m <a href="https://docs.localstack.cloud/user-guide/web-application/?ref=engineering.shopbase.com" rel="noreferrer">t&#x1EA1;i &#x111;&#xE2;y</a>. Tuy c&#xF2;n nhi&#x1EC1;u h&#x1EA1;n ch&#x1EBF; nh&#x1B0;ng t&#xF4;i th&#x1EA5;y &#x111;&#xE2;y l&#xE0; m&#x1ED9;t c&#xF4;ng c&#x1EE5; r&#x1EA5;t ti&#x1EC7;n cho c&#xE1;c b&#x1EA1;n trong qu&#xE1; tr&#xEC;nh th&#x1EF1;c h&#xE0;nh thao t&#xE1;c v&#x1EDB;i AWS.</p>]]></content:encoded></item><item><title><![CDATA[Optimize Core VueJS - OCG's Challenging Products (P2)]]></title><description><![CDATA[<h2 id="t%E1%BB%91i-%C6%B0u-web-performance">T&#x1ED1;i &#x1B0;u Web Performance</h2><p><strong>Modify Core VueJS &#x111;&#x1EC3; t&#x1ED1;i &#x1B0;u performance</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://mevn-public.s3-ap-southeast-1.amazonaws.com/marketenterprise.vn/wp-images/2021/04/06170614/vuejs-1568x939.png" class="kg-image" alt="vuejs l&#xE0; g&#xEC;" loading="lazy"><figcaption><span style="white-space: pre-wrap;">Image </span><a href="https://www.marketenterprise.vn/blog/vuejs-la-gi.html?ref=engineering.shopbase.com" rel="noreferrer"><span style="white-space: pre-wrap;">Source</span></a></figcaption></figure><p>S&#x1EED; d&#x1EE5;ng m&#x1ED9;t framework &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng s&#x1EA3;n ph&#x1EA9;m l&#xE0; m&#x1ED9;t c&#xF4;</p>]]></description><link>https://engineering.shopbase.com/ocgs-challenging-products-2024-p2/</link><guid isPermaLink="false">65bb177c95b8649d9ab037b1</guid><category><![CDATA[challenging-products]]></category><category><![CDATA[vuejs]]></category><category><![CDATA[performance]]></category><category><![CDATA[ssg]]></category><category><![CDATA[ssr]]></category><category><![CDATA[web]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Sun, 28 Jan 2024 04:07:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1653406759381-4d6ca279cab3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDZ8fHZ1ZWpzfGVufDB8fHx8MTcwNjc2MTQyOXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h2 id="t%E1%BB%91i-%C6%B0u-web-performance">T&#x1ED1;i &#x1B0;u Web Performance</h2><img src="https://images.unsplash.com/photo-1653406759381-4d6ca279cab3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDZ8fHZ1ZWpzfGVufDB8fHx8MTcwNjc2MTQyOXww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Optimize Core VueJS - OCG&apos;s Challenging Products (P2)"><p><strong>Modify Core VueJS &#x111;&#x1EC3; t&#x1ED1;i &#x1B0;u performance</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://mevn-public.s3-ap-southeast-1.amazonaws.com/marketenterprise.vn/wp-images/2021/04/06170614/vuejs-1568x939.png" class="kg-image" alt="Optimize Core VueJS - OCG&apos;s Challenging Products (P2)" loading="lazy"><figcaption><span style="white-space: pre-wrap;">Image </span><a href="https://www.marketenterprise.vn/blog/vuejs-la-gi.html?ref=engineering.shopbase.com" rel="noreferrer"><span style="white-space: pre-wrap;">Source</span></a></figcaption></figure><p>S&#x1EED; d&#x1EE5;ng m&#x1ED9;t framework &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng s&#x1EA3;n ph&#x1EA9;m l&#xE0; m&#x1ED9;t c&#xF4;ng vi&#x1EC7;c v&#x1EEB;a kh&#xF3;, v&#x1EEB;a d&#x1EC5;. V&#x1EDB;i c&#xE1;c s&#x1EA3;n ph&#x1EA9;m &#x1EDF; scale v&#x1EEB;a v&#xE0; nh&#x1ECF;, framework h&#x1EA7;u nh&#x1B0; &#x111;&#xE1;p &#x1EE9;ng &#x111;&#x1B0;&#x1EE3;c m&#x1ECD;i k&#x1EF3; v&#x1ECD;ng c&#x1EE7;a ch&#xFA;ng ta, v&#xE0; &#x111;&#xF3; c&#x169;ng l&#xE0; c&#xE1;ch ch&#xFA;ng &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng. Tuy nhi&#xEA;n, khi s&#x1EA3;n ph&#x1EA9;m b&#x1EAF;t &#x111;&#x1EA7;u &#x111;&#x1EA1;t l&#x1B0;&#x1EE3;ng ng&#x1B0;&#x1EDD;i d&#xF9;ng t&#x1B0;&#x1A1;ng &#x111;&#x1ED1;i l&#x1EDB;n, c&#xE1;c framework th&#x1B0;&#x1EDD;ng b&#x1EAF;t &#x111;&#x1EA7;u l&#x1ED9; ra c&#xE1;c y&#x1EBF;u &#x111;i&#x1EC3;m c&#x1EE7;a m&#xEC;nh. &#x110;&#xF3; l&#xE0; c&#x1A1; h&#x1ED9;i &#x111;&#x1EC3; &#x111;&#x1ED9;i ng&#x169; ph&#xE1;t tri&#x1EC3;n c&#xF3; th&#x1EC3; v&#x1ECD;c, t&#xEC;m hi&#x1EC3;u s&#xE2;u, t&#x1ED1;i &#x1B0;u ch&#xFA;ng.</p><p>T&#x1EA1;i OCG, VueJS l&#xE0; framework ch&#xED;nh &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng frontend (Code name: storefront next). Khi c&#xE1;c t&#xED;nh n&#x103;ng s&#x1EA3;n ph&#x1EA9;m &#x111;&#x1B0;&#x1EE3;c th&#xEA;m v&#xE0;o nhi&#x1EC1;u &#x111;&#x1EC3; &#x111;&#xE1;p &#x1EE9;ng &#x111;&#x1B0;&#x1EE3;c nhu c&#x1EA7;u ng&#x1B0;&#x1EDD;i d&#xF9;ng th&#xEC; b&#xE0;i to&#xE1;n t&#x1ED1;i &#x1B0;u performance, x&#x1EED; l&#xFD; l&#x1ED7;i tr&#x1EDF; n&#xEA;n r&#x1EA5;t c&#x1EA7;n thi&#x1EBF;t.</p><p>&#x110;&#x1EC3; &#x111;&#x1EA1;t &#x111;&#x1B0;&#x1EE3;c &#x111;i&#x1EC3;m Google Pagespeed &gt; 90 v&#x1EDB;i m&#x1ED9;t h&#x1EC7; th&#x1ED1;ng website ph&#x1EE9;c t&#x1EA1;p l&#xE0; &#x111;i&#x1EC1;u r&#x1EA5;t kh&#xF3; - nh&#x1B0;ng l&#xE0; &#x111;i&#x1EC1;u OCG &#x111;ang h&#x1B0;&#x1EDB;ng t&#x1EDB;i. Vi&#x1EC7;c n&#xE0;y &#x111;&#xF2;i h&#x1ECF;i ph&#x1EA3;i hi&#x1EC3;u r&#x1EA5;t s&#xE2;u v&#x1EC1; c&#xE1;ch ho&#x1EA1;t &#x111;&#x1ED9;ng b&#xEA;n trong c&#x1EE7;a Core VueJS, Composition API, VueX/Pinia&#x2026;&#x111;&#x1EC3; bi&#x1EBF;t &#x111;&#x1B0;&#x1EE3;c qu&#xE1; tr&#xEC;nh build/change DOM, node, hydration&#x2026;v&#xE0; sau &#x111;&#xF3; c&#x1EA7;n ph&#x1EA3;i optimize ch&#xFA;ng cho ph&#xF9; h&#x1EE3;p v&#x1EDB;i b&#xE0;i to&#xE1;n t&#x1EA1;i OCG.</p><p>Vi&#x1EC7;c t&#x1ED1;i &#x1B0;u performance cho Core VueJS l&#xE0; m&#x1ED9;t c&#xF4;ng vi&#x1EC7;c ph&#x1EE9;c t&#x1EA1;p v&#xE0; &#x111;&#xF2;i h&#x1ECF;i nhi&#x1EC1;u ki&#x1EBF;n th&#x1EE9;c, kinh nghi&#x1EC7;m. N&#xF3; bao g&#x1ED3;m c&#xE1;c kh&#xED;a c&#x1EA1;nh sau:</p><ul><li>T&#x1ED1;i &#x1B0;u qu&#xE1; tr&#xEC;nh build DOM: &#x110;&#xE2;y l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng y&#x1EBF;u t&#x1ED1; quan tr&#x1ECD;ng nh&#x1EA5;t &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n performance c&#x1EE7;a VueJS. C&#xF3; nhi&#x1EC1;u c&#xE1;ch &#x111;&#x1EC3; t&#x1ED1;i &#x1B0;u qu&#xE1; tr&#xEC;nh n&#xE0;y, ch&#x1EB3;ng h&#x1EA1;n nh&#x1B0; s&#x1EED; d&#x1EE5;ng virtual DOM, lazy loading, minify code,...</li><li>T&#x1ED1;i &#x1B0;u qu&#xE1; tr&#xEC;nh change DOM: Qu&#xE1; tr&#xEC;nh n&#xE0;y x&#x1EA3;y ra khi c&#xE1;c gi&#xE1; tr&#x1ECB; c&#x1EE7;a c&#xE1;c component thay &#x111;&#x1ED5;i. C&#xF3; th&#x1EC3; t&#x1ED1;i &#x1B0;u qu&#xE1; tr&#xEC;nh n&#xE0;y b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xE1;c k&#x1EF9; thu&#x1EAD;t nh&#x1B0; lazy render, memoization,...</li><li>T&#x1ED1;i &#x1B0;u qu&#xE1; tr&#xEC;nh hydration: Hydration l&#xE0; qu&#xE1; tr&#xEC;nh chuy&#x1EC3;n &#x111;&#x1ED5;i d&#x1EEF; li&#x1EC7;u t&#x1EEB; server sang client. C&#xF3; th&#x1EC3; t&#x1ED1;i &#x1B0;u qu&#xE1; tr&#xEC;nh n&#xE0;y b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xE1;c k&#x1EF9; thu&#x1EAD;t nh&#x1B0; lazy hydration,...</li></ul><h2 id="bi%E1%BA%BFn-vuejs-th%C3%A0nh-m%E1%BB%99t-emplate-engine">Bi&#x1EBF;n VueJS th&#xE0;nh m&#x1ED9;t emplate Engine</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn.shortpixel.ai/client/to_webp,q_glossy,ret_img,w_746/https://www.indusface.com/wp-content/uploads/2019/11/template-engine.png" class="kg-image" alt="Optimize Core VueJS - OCG&apos;s Challenging Products (P2)" loading="lazy"><figcaption><span style="white-space: pre-wrap;">Image </span><a href="https://cdn.shortpixel.ai/client/to_webp,q_glossy,ret_img,w_746/https://www.indusface.com/wp-content/uploads/2019/11/template-engine.png?ref=engineering.shopbase.com"><span style="white-space: pre-wrap;">Source</span></a></figcaption></figure><p>VueJS SSG l&#xE0; m&#x1ED9;t k&#x1EF9; thu&#x1EAD;t optimize t&#x1ED1;c &#x111;&#x1ED9; c&#x1EE7;a c&#xE1;c &#x1EE9;ng d&#x1EE5;ng web s&#x1EED; d&#x1EE5;ng VueJS.</p><p>V&#x1EC1; c&#x1A1; b&#x1EA3;n, VueJS &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng &#x111;&#x1EC3; l&#xE0;m framework ph&#xED;a client, n&#x1A1;i m&#xE0; theo m&#x1EB7;c &#x111;&#x1ECB;nh, c&#xE1;c th&#xE0;nh ph&#x1EA7;n Vue t&#x1EA1;o v&#xE0; thao t&#xE1;c DOM tr&#x1EF1;c ti&#x1EBF;p trong tr&#xEC;nh duy&#x1EC7;t. Tuy nhi&#xEA;n, n&#xF3; c&#x169;ng cho ph&#xE9;p render c&#xE1;c th&#xE0;nh ph&#x1EA7;n t&#x1B0;&#x1A1;ng t&#x1EF1; th&#xE0;nh HTML content tr&#xEA;n m&#xE1;y ch&#x1EE7; (SSR). Sau &#x111;&#xF3;, HTML content n&#xE0;y c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c g&#x1EED;i tr&#x1EF1;c ti&#x1EBF;p &#x111;&#x1EBF;n tr&#xEC;nh duy&#x1EC7;t v&#xE0; &quot;hydrate&quot; (bind event v&#xE0;o c&#xE1;c nodes) &#x111;&#x1EC3; bi&#x1EBF;n &#x111;&#x1ED5;i &#x111;&#xE1;nh d&#x1EA5;u t&#x129;nh th&#xE0;nh m&#x1ED9;t &#x1EE9;ng d&#x1EE5;ng t&#x1B0;&#x1A1;ng t&#xE1;c &#x111;&#x1EA7;y &#x111;&#x1EE7; tr&#xEA;n ph&#xED;a client.</p><p>SSR l&#xE0; m&#x1ED9;t k&#x1EF9; thu&#x1EAD;t hi&#x1EC7;u qu&#x1EA3; &#x111;&#x1EC3; t&#x103;ng t&#x1ED1;c &#x111;&#x1ED9; t&#x1EA3;i trang, nh&#x1B0;ng n&#xF3; c&#xF3; m&#x1ED9;t s&#x1ED1; h&#x1EA1;n ch&#x1EBF;. &#x110;&#x1EA7;u ti&#xEA;n, SSR y&#xEA;u c&#x1EA7;u render l&#x1EA1;i to&#xE0;n b&#x1ED9; &#x1EE9;ng d&#x1EE5;ng m&#x1ED7;i khi c&#xF3; thay &#x111;&#x1ED5;i d&#x1EEF; li&#x1EC7;u. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; th&#x1EC3; g&#xE2;y ra &#x111;&#x1ED9; tr&#x1EC5; &#x111;&#xE1;ng k&#x1EC3; n&#x1EBF;u d&#x1EEF; li&#x1EC7;u thay &#x111;&#x1ED5;i th&#x1B0;&#x1EDD;ng xuy&#xEA;n. Th&#x1EE9; hai, SSR c&#xF3; th&#x1EC3; l&#xE0;m t&#x103;ng k&#xED;ch th&#x1B0;&#x1EDB;c &#x1EE9;ng d&#x1EE5;ng, v&#xEC; n&#xF3; c&#x1EA7;n ph&#x1EA3;i ch&#x1EE9;a c&#x1EA3; m&#xE3; VueJS v&#xE0; HTML content &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c render.</p><p>SSG l&#xE0; m&#x1ED9;t k&#x1EF9; thu&#x1EAD;t c&#xF3; th&#x1EC3; kh&#x1EAF;c ph&#x1EE5;c &#x111;&#x1B0;&#x1EE3;c nh&#x1EEF;ng h&#x1EA1;n ch&#x1EBF; c&#x1EE7;a SSR. SSG ho&#x1EA1;t &#x111;&#x1ED9;ng b&#x1EB1;ng c&#xE1;ch render &#x1EE9;ng d&#x1EE5;ng th&#xE0;nh HTML t&#x129;nh tr&#xEA;n m&#xE1;y ch&#x1EE7; tr&#x1B0;&#x1EDB;c khi g&#x1EED;i n&#xF3; &#x111;&#x1EBF;n tr&#xEC;nh duy&#x1EC7;t. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; ngh&#x129;a l&#xE0; &#x1EE9;ng d&#x1EE5;ng ch&#x1EC9; c&#x1EA7;n render m&#x1ED9;t l&#x1EA7;n, ngay c&#x1EA3; khi d&#x1EEF; li&#x1EC7;u thay &#x111;&#x1ED5;i. Ngo&#xE0;i ra, SSG c&#xF3; th&#x1EC3; gi&#xFA;p gi&#x1EA3;m k&#xED;ch th&#x1B0;&#x1EDB;c &#x1EE9;ng d&#x1EE5;ng, v&#xEC; n&#xF3; ch&#x1EC9; c&#x1EA7;n ch&#x1EE9;a m&#xE3; VueJS.</p><p>Tuy nhi&#xEA;n, SSG c&#x169;ng c&#xF3; m&#x1ED9;t s&#x1ED1; th&#xE1;ch th&#x1EE9;c ri&#xEA;ng. M&#x1ED9;t th&#xE1;ch th&#x1EE9;c l&#xE0; SSG y&#xEA;u c&#x1EA7;u c&#xE1;c nh&#xE0; ph&#xE1;t tri&#x1EC3;n ph&#x1EA3;i suy ngh&#x129; tr&#x1B0;&#x1EDB;c v&#x1EC1; d&#x1EEF; li&#x1EC7;u m&#xE0; h&#x1ECD; s&#x1EBD; c&#x1EA7;n &#x111;&#x1EC3; render &#x1EE9;ng d&#x1EE5;ng. &#x110;i&#x1EC1;u n&#xE0;y c&#xF3; th&#x1EC3; khi&#x1EBF;n vi&#x1EC7;c ph&#xE1;t tri&#x1EC3;n &#x1EE9;ng d&#x1EE5;ng tr&#x1EDF; n&#xEA;n ph&#x1EE9;c t&#x1EA1;p h&#x1A1;n. M&#x1ED9;t th&#xE1;ch th&#x1EE9;c kh&#xE1;c l&#xE0; SSG c&#xF3; th&#x1EC3; kh&#xF3; b&#x1EA3;o tr&#xEC;, v&#xEC; c&#xE1;c nh&#xE0; ph&#xE1;t tri&#x1EC3;n c&#x1EA7;n ph&#x1EA3;i c&#x1EAD;p nh&#x1EAD;t HTML t&#x129;nh khi d&#x1EEF; li&#x1EC7;u thay &#x111;&#x1ED5;i.</p><p>OCG &#x111;ang nghi&#xEA;n c&#x1EE9;u m&#x1ED9;t gi&#x1EA3;i ph&#xE1;p SSG cho VueJS. Gi&#x1EA3;i ph&#xE1;p n&#xE0;y s&#x1EBD; gi&#x1EA3;i quy&#x1EBF;t c&#xE1;c th&#xE1;ch th&#x1EE9;c c&#x1EE7;a SSG b&#x1EB1;ng c&#xE1;ch s&#x1EED; d&#x1EE5;ng c&#xE1;c k&#x1EF9; thu&#x1EAD;t m&#x1EDB;i. V&#xED; d&#x1EE5;, gi&#x1EA3;i ph&#xE1;p s&#x1EBD; s&#x1EED; d&#x1EE5;ng m&#x1ED9;t h&#x1EC7; th&#x1ED1;ng qu&#x1EA3;n l&#xFD; d&#x1EEF; li&#x1EC7;u &#x111;&#x1EC3; l&#x1B0;u tr&#x1EEF; d&#x1EEF; li&#x1EC7;u c&#x1EA7;n thi&#x1EBF;t cho SSG. &#x110;i&#x1EC1;u n&#xE0;y s&#x1EBD; gi&#xFA;p c&#xE1;c nh&#xE0; ph&#xE1;t tri&#x1EC3;n d&#x1EC5; d&#xE0;ng c&#x1EAD;p nh&#x1EAD;t d&#x1EEF; li&#x1EC7;u v&#xE0; gi&#x1EA3;m thi&#x1EC3;u nhu c&#x1EA7;u suy ngh&#x129; tr&#x1B0;&#x1EDB;c v&#x1EC1; d&#x1EEF; li&#x1EC7;u c&#x1EA7;n thi&#x1EBF;t.</p><p>Gi&#x1EA3;i ph&#xE1;p SSG c&#x1EE7;a OCG v&#x1EAB;n &#x111;ang trong qu&#xE1; tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n, nh&#x1B0;ng n&#xF3; c&#xF3; ti&#x1EC1;m n&#x103;ng mang l&#x1EA1;i nh&#x1EEF;ng c&#x1EA3;i ti&#x1EBF;n &#x111;&#xE1;ng k&#x1EC3; v&#x1EC1; t&#x1ED1;c &#x111;&#x1ED9; v&#xE0; hi&#x1EC7;u su&#x1EA5;t cho c&#xE1;c &#x1EE9;ng d&#x1EE5;ng web s&#x1EED; d&#x1EE5;ng VueJS.</p>]]></content:encoded></item><item><title><![CDATA[Defeating SQL Injection Attacks in Go: Preventing at scale]]></title><description><![CDATA[<p><em>We all know that the most effective way to prevent SQLi is to use Prepared Statement. But to apply Prepared Statement at scale to all repositories in an organization is not as simple as imagined.</em></p><h2 id="sql-injection-vulnerability">SQL Injection vulnerability</h2>
<blockquote>
<p>SQL injection (SQLi) is a web security vulnerability that allows an attacker</p></blockquote>]]></description><link>https://engineering.shopbase.com/defeating-sql-injection-attacks-in-go-preventing-at-scale/</link><guid isPermaLink="false">65bb117795b8649d9ab036fe</guid><category><![CDATA[security]]></category><dc:creator><![CDATA[Le Linh]]></dc:creator><pubDate>Sun, 28 Jan 2024 03:47:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/prevent_sqli-1.webp" medium="image"/><content:encoded><![CDATA[<img src="https://engineering.shopbase.com/content/images/2024/02/prevent_sqli-1.webp" alt="Defeating SQL Injection Attacks in Go: Preventing at scale"><p><em>We all know that the most effective way to prevent SQLi is to use Prepared Statement. But to apply Prepared Statement at scale to all repositories in an organization is not as simple as imagined.</em></p><h2 id="sql-injection-vulnerability">SQL Injection vulnerability</h2>
<blockquote>
<p>SQL injection (SQLi) is a web security vulnerability that allows an attacker to interfere with the queries that an application makes to its database.</p>
</blockquote>
<p><img src="https://engineering.shopbase.com/content/images/2024/02/sql.webp" alt="Defeating SQL Injection Attacks in Go: Preventing at scale" loading="lazy"></p>
<p>Ngu&#x1ED3;n: <a href="https://portswigger.net/web-security/sql-injection?ref=engineering.shopbase.com#:~:text=SQL%20injection%20(SQLi)%20is%20a,not%20normally%20able%20to%20retrieve.">portswigger</a></p>
<h2 id="prepared-statement">Prepared Statement</h2>
<p>Sure! T&#x1EA5;t c&#x1EA3; ch&#xFA;ng ta &#x111;&#x1EC1;u bi&#x1EBF;t r&#x1EB1;ng c&#xE1;ch hi&#x1EC7;u qu&#x1EA3; nh&#x1EA5;t &#x111;&#x1EC3; ng&#x103;n ch&#x1EB7;n SQLi l&#xE0; s&#x1EED; d&#x1EE5;ng Prepared Statement. Prepared Statement l&#xE0; m&#x1ED9;t t&#xED;nh n&#x103;ng c&#x1EE7;a database cho ph&#xE9;p b&#x1EA1;n &#x111;&#x1ECB;nh ngh&#x129;a SQL query template v&#x1EDB;i c&#xE1;c placeholders cho tham s&#x1ED1;. SQL query template &#x111;&#x1B0;&#x1EE3;c bi&#xEA;n d&#x1ECB;ch tr&#x1B0;&#x1EDB;c v&#xE0; l&#x1B0;u tr&#x1EEF; tr&#xEA;n m&#xE1;y ch&#x1EE7; c&#x1A1; s&#x1EDF; d&#x1EEF; li&#x1EC7;u, sau &#x111;&#xF3; b&#x1EA1;n c&#xF3; th&#x1EC3; cung c&#x1EA5;p c&#xE1;c gi&#xE1; tr&#x1ECB; tham s&#x1ED1; c&#x1EE5; th&#x1EC3; &#x111;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n truy v&#x1EA5;n nhi&#x1EC1;u l&#x1EA7;n m&#xE0; kh&#xF4;ng c&#x1EA7;n bi&#xEA;n d&#x1ECB;ch l&#x1EA1;i.</p>
<p>Qu&#xE1; tr&#xEC;nh s&#x1EED;  d&#x1EE5;ng Prepared Statement bao g&#x1ED3;m 2 b&#x1B0;&#x1EDB;c:</p>
<ol>
<li>Prepare: Database nh&#x1EAD;n SQL query template v&#xE0; bi&#xEA;n d&#x1ECB;ch n&#xF3; v&#xE0;o trong execution plan, t&#x1ED1;i &#x1B0;u h&#xF3;a truy v&#x1EA5;n &#x111;&#x1EC3; n&#xE2;ng cao hi&#x1EC7;u su&#x1EA5;t. C&#xE1;c placeholder trong template &#x111;&#x1EA1;i di&#x1EC7;n c&#xE1;c tham s&#x1ED1; s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c cung c&#x1EA5;p gi&#xE1; tr&#x1ECB; sau &#x111;&#xF3;.</li>
<li>Execute: Sau khi Prepared Statement &#x111;&#x1B0;&#x1EE3;c t&#x1EA1;o, b&#x1EA1;n c&#xF3; th&#x1EC3; cung c&#x1EA5;p c&#xE1;c gi&#xE1; tr&#x1ECB; cho tham s&#x1ED1; &#x111;&#x1EC3; n&#xF3; th&#x1EF1;c thi query. M&#xE1;y ch&#x1EE7; database s&#x1EED; d&#x1EE5;ng precompiled execution plan v&#xE0; ch&#x1EC9; c&#x1EA7;n thay th&#x1EBF; gi&#xE1; tr&#x1ECB; tham s&#x1ED1;, l&#xE0;m cho vi&#x1EC7;c th&#x1EF1;c thi hi&#x1EC7;u qu&#x1EA3; h&#x1A1;n c&#xE1;ch th&#x1EF1;c thi c&#x1EE7;a c&#xE1;c SQL query th&#xF4;ng th&#x1B0;&#x1EDD;ng.</li>
</ol>
<p>Prepared Statement c&#xF3; th&#x1EC3; ng&#x103;n SQL injection v&#xEC; n&#xF3; t&#x1EF1; &#x111;&#x1ED9;ng x&#x1EED; l&#xFD; escape v&#xE0; bind param, t&#x1EEB; &#x111;&#xF3; coi tham s&#x1ED1; truy&#x1EC1;n v&#xE0;o SQL query l&#xE0; data ch&#x1EE9; kh&#xF4;ng ph&#x1EA3;i l&#xE0; code c&#xF3; th&#x1EC3; th&#x1EF1;c thi.</p>
<h2 id="squirrel">Squirrel</h2>
<p>Squirrel l&#xE0; m&#x1ED9;t th&#x1B0; vi&#x1EC7;n Golang ph&#x1ED5; bi&#x1EBF;n cho vi&#x1EC7;c x&#x1EED; l&#xFD; SQL query gi&#xFA;p b&#x1EA1;n x&#xE2;y d&#x1EF1;ng SQL query v&#xE0; &#x111;&#x1A1;n gi&#x1EA3;n h&#xF3;a t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i database v&#xE0; n&#xE2;ng cao hi&#x1EC7;u xu&#x1EA5;t l&#x1EAD;p tr&#xEC;nh. Nh&#x1B0;ng &#x111;i&#x1EC1;u n&#xE0;y kh&#xF4;ng c&#xF3; ngh&#x129;a l&#xE0; s&#x1EED; d&#x1EE5;ng squirrel s&#x1EBD; m&#x1EB7;c &#x111;&#x1ECB;nh gi&#x1EEF; cho &#x1EE9;ng d&#x1EE5;ng c&#x1EE7;a b&#x1EA1;n an to&#xE0;n kh&#x1ECF;i SQL injection.</p>
<p>Ph&#x1EA1;m vi c&#x1EE7;a b&#xE0;i vi&#x1EBF;t n&#xE0;y s&#x1EBD; ch&#x1EC9; t&#x1EAD;p trung v&#xE0;o vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng squirrel, v&#x1EDB;i c&#xE1;c th&#x1B0; vi&#x1EC7;n kh&#xE1;c, b&#x1EA1;n v&#x1EAB;n c&#xF3; th&#x1EC3; &#xE1;p d&#x1EE5;ng t&#x1B0;&#x1A1;ng t&#x1EF1;.</p>
<h2 id="bad-practices">Bad practices</h2>
<pre><code class="language-golang">func Vul_Func(tableName string, ids []int64, name string) (string, []interface{}, error) {
	idString := make([]string, 0)

	for _, id := range ids {
		idString = append(idString, fmt.Sprintf(&quot;%d&quot;, id))
	}

	query := squirrel.Select(&quot;*&quot;).
		From(tableName).
		Where(squirrel.Expr(fmt.Sprintf(&quot;id IN (%v)&quot;, strings.Join(idString, &quot;,&quot;)))).
		Where(squirrel.Expr(fmt.Sprintf(&quot;name LIKE &apos;%%%v%%&apos;&quot;, name)))

	sqlQuery, args, err := query.ToSql()
	if err != nil {
		log.Fatal(err)
	}
// Print the generated query and arguments
	fmt.Println(&quot;query:&quot;, sqlQuery)
	fmt.Println(&quot;agrs:&quot;, args)
}
</code></pre>
<p>&#x110;o&#x1EA1;n code tr&#xEA;n s&#x1EED; d&#x1EE5;ng h&#xE0;m fmt.Sptrintf &#x111;&#x1EC3; build query b&#xEA;n trong h&#xE0;m squirrel.Expr. Vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng truy v&#x1EA5;n nh&#x1B0; v&#x1EAD;y ngh&#x129;a l&#xE0; b&#x1EA1;n &#x111;ang n&#x1ED1;i tr&#x1EF1;c ti&#x1EBF;p d&#x1EEF; li&#x1EC7;u &#x111;&#x1EA7;u v&#xE0;o t&#x1EEB; user v&#xE0;o truy v&#x1EA5;n, &#x111;&#xE2;y l&#xE0; c&#xE1;ch l&#xE0;m kh&#xF4;ng an to&#xE0;n v&#xE0; khi&#x1EBF;n cho &#x111;o&#x1EA1;n code c&#x1EE7;a b&#x1EA1;n t&#x1ED3;n t&#x1EA1;i l&#x1ED7; h&#x1ED5;ng. N&#x1EBF;u print query &#x111;&#x1B0;&#x1EE3;c build  theo c&#xE1;ch tr&#xEA;n ra console th&#xEC; s&#x1EBD; tr&#xF4;ng nh&#x1B0; sau:</p>
<pre><code>query: SELECT * FROM users WHERE id IN (1,2,3) AND name LIKE &apos;%fuzz OR 1=1%&apos;
args: []
</code></pre>
<p>Tham s&#x1ED1; args l&#xE0; m&#x1EA3;ng r&#x1ED7;ng [] v&#xE0; user input &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c n&#x1ED1;i tr&#x1EF1;c ti&#x1EBF;p v&#xE0;o query.</p>
<h2 id="good-practices">Good practices</h2>
<pre><code class="language-golang">func Safe_Func(tableName string, ids []int64, name string) (string, []interface{}, error) {
	idString := make([]string, 0)

	for _, id := range ids {
		idString = append(idString, fmt.Sprintf(&quot;%d&quot;, id))
	}

	query := squirrel.Select(&quot;*&quot;).
		From(tableName).
		Where(squirrel.Expr(&quot;id IN (&quot;+squirrel.Placeholders(len(idsArgs))+&quot;)&quot;, idsArgs...)).
		Where(squirrel.Expr(&quot;name LIKE ?&quot;, fmt.Sprintf(&quot;%%%v%%&quot;, name)))

	sqlQuery, args, err := query.ToSql()
	if err != nil {
		log.Fatal(err)
	}
// Print the generated query and arguments
	fmt.Println(&quot;query:&quot;, sqlQuery)
	fmt.Println(&quot;agrs:&quot;, args)
}
</code></pre>
<p>&#x110;&#x1EC3; fix l&#x1ED7;i tr&#xEA;n, ch&#xFA;ng ta c&#x1EA7;n s&#x1EED; d&#x1EE5;ng &#x111;&#xFA;ng query parameter b&#x1EB1;ng vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng placeholder ? cho c&#xE1;c tham s&#x1ED1;. N&#x1EBF;u print query &#x111;&#x1B0;&#x1EE3;c build  theo c&#xE1;ch n&#xE0;y ra console th&#xEC; s&#x1EBD; tr&#xF4;ng nh&#x1B0; sau:</p>
<pre><code>query: SELECT * FROM users WHERE id IN (?,?,?) AND name LIKE ?
args: [1 2 3 %fuzz OR 1=1%]
</code></pre>
<p>Nh&#x1B0; b&#x1EA1;n c&#xF3; th&#x1EC3; th&#x1EA5;y, input kh&#xF4;ng an to&#xE0;n b&#xE2;y gi&#x1EDD; &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c truy&#x1EC1;n v&#xE0;o arg thay v&#xEC; n&#x1ED1;i tr&#x1EF1;c ti&#x1EBF;p v&#xE0;o c&#xE2;u truy v&#x1EA5;n.</p>
<h2 id="detect-using-string-builder-at-scale">Detect using string builder at scale</h2>
<p>N&#x1EBF;u b&#x1EA1;n &#x111;ang &#x111;&#x1EA3;m nh&#x1EAD;n task ph&#xE1;t hi&#x1EC7;n v&#xE0; fix t&#x1EA5;t c&#x1EA3; c&#xE1;c v&#x1ECB; tr&#xED; s&#x1EED; d&#x1EE5;ng string builder nh&#x1B0; v&#xED; d&#x1EE5; &#x1EDF; ph&#x1EA7;n bad practices, b&#x1EA1;n s&#x1EBD; l&#xE0;m g&#xEC;? B&#x1EA1;n c&#xF3; th&#x1EC3; &#x111;i h&#x1ECF;i t&#x1EA5;t c&#x1EA3; c&#xE1;c L&#x1EAD;p tr&#xEC;nh vi&#xEA;n trong c&#xF4;ng ty &#x111;&#x1EC3; nh&#x1EDB; l&#x1EA1;i t&#x1EA5;t c&#x1EA3; c&#xE1;c v&#x1ECB; tr&#xED; m&#xEC;nh &#x111;&#xE3; s&#x1EED; d&#x1EE5;ng string builder &#x111;&#x1EC3; x&#x1EED; l&#xFD;.</p>
<p>Nh&#xEC;n chung, c&#xF3; nhi&#x1EC1;u c&#xE1;ch &#x111;&#x1EC3; ch&#xFA;ng ta l&#xE0;m xong task nh&#x1B0;ng th&#x1EDD;i gian c&#x1EE7;a ch&#xFA;ng ta kh&#xF4;ng nhi&#x1EC1;u. N&#x1EBF;u b&#x1EA1;n tinh &#xFD;, b&#x1EA1;n c&#xF3; th&#x1EC3; th&#x1EA5;y gi&#x1EA3;i ph&#xE1;p cho task n&#xE0;y th&#xF4;ng qua 2 v&#xED; d&#x1EE5; m&#xE0; t&#xF4;i show &#x1EDF; tr&#xEA;n. Gi&#x1EA3;i ph&#xE1;p l&#xE0; scan t&#x1EA5;t c&#x1EA3; query &#x111;&#x1B0;&#x1EE3;c x&#x1EED; l&#xFD; b&#x1EDF;i driver v&#xE0; n&#x1EBF;u query th&#x1ECF;a m&#xE3;n 2 ti&#xEA;u ch&#xED; sau, n&#xF3; l&#xE0; query t&#x1ED3;n t&#x1EA1;i l&#x1ED7; h&#x1ED5;ng SQL injection:</p>
<ol>
<li>query s&#x1EED; d&#x1EE5;ng m&#x1EC7;nh &#x111;&#x1EC1; where</li>
<li>Kh&#xF4;ng ch&#x1EE9;a b&#x1EA5;t k&#x1EF3; arguments, gi&#xE1; tr&#x1ECB; args l&#xE0; m&#x1ED9;t m&#x1EA3;ng r&#x1ED7;ng nh&#x1B0; trong v&#xED; d&#x1EE5; Bad practices</li>
</ol>
<p><img src="https://engineering.shopbase.com/content/images/2024/02/prevent_sqli.webp" alt="Defeating SQL Injection Attacks in Go: Preventing at scale" loading="lazy"></p>
<p>Logic gi&#x1EA3; m&#xE3; cho ph&#x1B0;&#x1A1;ng ph&#xE1;p n&#xE0;y &#x111;&#x1B0;&#x1EE3;c tr&#xEC;nh b&#xE0;y nh&#x1B0; sau:</p>
<pre><code class="language-golang">sqlQuery, args, err := query.ToSql()
lenArgs = len(args)
if strings.Contains(query, &quot;where&quot;) &amp;&amp; lenArgs == 0 {
   // return Alert location is using string builder to build query.
}
</code></pre>
<p>C&#x1EA3;m &#x1A1;n &#x111;&#xE3; b&#x1EA1;n &#x111;&#xE3; &#x111;&#x1ECD;c!</p>
]]></content:encoded></item><item><title><![CDATA[Security - OCG's Challenging Products (P3)]]></title><description><![CDATA[<h2 id="%C3%A1p-d%E1%BB%A5ng-chu%E1%BA%A9n-b%E1%BA%A3o-m%E1%BA%ADt-cao-nh%E1%BA%A5t-v%C3%A0o-shopbase">&#xC1;p d&#x1EE5;ng chu&#x1EA9;n b&#x1EA3;o m&#x1EAD;t cao nh&#x1EA5;t v&#xE0;o ShopBase</h2><p>X&#x1EED; l&#xFD; c&#xE1;c lu&#x1ED3;ng thanh to&#xE1;n l&#xE0; m&#x1ED9;t c&#xF4;ng vi&#x1EC7;c ph&#x1EE9;c</p>]]></description><link>https://engineering.shopbase.com/security-ocgs-challenging-products-2024-p3/</link><guid isPermaLink="false">65bb197895b8649d9ab037f4</guid><category><![CDATA[security]]></category><category><![CDATA[challenging-products]]></category><category><![CDATA[checkout]]></category><category><![CDATA[infrastructure]]></category><category><![CDATA[pci-dss]]></category><category><![CDATA[soc-2]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Fri, 26 Jan 2024 04:10:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1618060932014-4deda4932554?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDM0fHxzZWN1cml0eXxlbnwwfHx8fDE3MDY3NjI5NDR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h2 id="%C3%A1p-d%E1%BB%A5ng-chu%E1%BA%A9n-b%E1%BA%A3o-m%E1%BA%ADt-cao-nh%E1%BA%A5t-v%C3%A0o-shopbase">&#xC1;p d&#x1EE5;ng chu&#x1EA9;n b&#x1EA3;o m&#x1EAD;t cao nh&#x1EA5;t v&#xE0;o ShopBase</h2><img src="https://images.unsplash.com/photo-1618060932014-4deda4932554?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDM0fHxzZWN1cml0eXxlbnwwfHx8fDE3MDY3NjI5NDR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Security - OCG&apos;s Challenging Products (P3)"><p>X&#x1EED; l&#xFD; c&#xE1;c lu&#x1ED3;ng thanh to&#xE1;n l&#xE0; m&#x1ED9;t c&#xF4;ng vi&#x1EC7;c ph&#x1EE9;c t&#x1EA1;p, &#x111;&#xF2;i h&#x1ECF;i s&#x1EF1; t&#x1EC9; m&#x1EC9;, c&#x1EA9;n th&#x1EAD;n v&#xE0; &#x111;&#x1EB7;c bi&#x1EC7;t, hi&#x1EC3;u bi&#x1EBF;t s&#xE2;u s&#x1EAF;c v&#x1EC1; b&#x1EA3;o m&#x1EAD;t. Th&#xF4;ng tin th&#x1EBB; t&#xED;n d&#x1EE5;ng/ghi n&#x1EE3; l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng th&#xF4;ng tin quan tr&#x1ECD;ng nh&#x1EA5;t c&#x1EE7;a ch&#xFA;ng ta. Ch&#x1EAF;c h&#x1EB3;n b&#x1EA1;n s&#x1EBD; kh&#xE1; c&#xE2;n nh&#x1EAF;c xem c&#xF3; n&#xEA;n &#x111;i&#x1EC1;n th&#xF4;ng tin th&#x1EBB; c&#x1EE7;a m&#xEC;nh v&#xE0;o m&#x1ED9;t website hay kh&#xF4;ng, nh&#x1EA5;t l&#xE0; c&#xE1;c website &#xED;t t&#xEA;n tu&#x1ED5;i, kh&#xF4;ng c&#xF3; ch&#x1EE9;ng ch&#x1EC9; b&#x1EA3;o m&#x1EAD;t.</p><p>ShopBase cung c&#x1EA5;p gi&#x1EA3;i ph&#xE1;p t&#x1ED5;ng th&#x1EC3; cho vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng v&#xE0; v&#x1EAD;n h&#xE0;nh m&#x1ED9;t trang web th&#x1B0;&#x1A1;ng m&#x1EA1;i &#x111;i&#x1EC7;n t&#x1EED;, bao g&#x1ED3;m qu&#x1EA3;n l&#xFD; h&#xE0;ng h&#xF3;a, &#x111;&#x1A1;n h&#xE0;ng v&#xE0; ph&#xE1;t tri&#x1EC3;n c&#x1ED5;ng thanh to&#xE1;n. Ngo&#xE0;i ra, ShopBase c&#xF2;n cung c&#x1EA5;p c&#xE1;c s&#x1EA3;n ph&#x1EA9;m li&#xEA;n quan &#x111;&#x1EBF;n thanh to&#xE1;n nh&#x1B0; ShopBase Payment, gi&#xFA;p ng&#x1B0;&#x1EDD;i b&#xE1;n h&#xE0;ng &#x1EDF; c&#xE1;c n&#x1B0;&#x1EDB;c &#x111;ang ph&#xE1;t tri&#x1EC3;n c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng c&#xE1;c c&#x1ED5;ng thanh to&#xE1;n l&#x1EDB;n nh&#x1B0; Stripe, PayPal m&#x1ED9;t c&#xE1;ch d&#x1EC5; d&#xE0;ng.</p><p>M&#x1ED9;t v&#x1EA5;n &#x111;&#x1EC1; quan tr&#x1ECD;ng &#x111;&#x1ED1;i v&#x1EDB;i m&#x1ECD;i c&#xF4;ng ty v&#x1EAD;n h&#xE0;nh c&#x1ED5;ng thanh to&#xE1;n l&#xE0; b&#x1EA3;o m&#x1EAD;t d&#x1EEF; li&#x1EC7;u c&#x1EE7;a kh&#xE1;ch h&#xE0;ng v&#xE0; th&#xF4;ng tin th&#x1EBB; c&#x1EE7;a h&#x1ECD;. T&#x1EA1;i ShopBase, ch&#xFA;ng t&#xF4;i &#x111;&#xE3; v&#xE0; &#x111;ang nghi&#xEA;n c&#x1EE9;u r&#x1EA5;t nhi&#x1EC1;u c&#xF4;ng ngh&#x1EC7; v&#xE0; k&#x1EF9; thu&#x1EAD;t &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o &#x111;i&#x1EC1;u n&#xE0;y.</p><p>T&#x1EEB; vi&#x1EC7;c &#x111;&#x1EA3;m b&#x1EA3;o an to&#xE0;n khi ng&#x1B0;&#x1EDD;i d&#xF9;ng &#x111;i&#x1EC1;n th&#xF4;ng tin th&#x1EBB; tr&#xEA;n website, qua &#x111;&#x1B0;&#x1EDD;ng truy&#x1EC1;n, &#x111;&#x1EBF;n vi&#x1EC7;c l&#x1B0;u tr&#x1EEF; l&#x1EA1;i trong h&#x1EC7; th&#x1ED1;ng, ch&#xFA;ng t&#xF4;i &#x111;&#x1EC1;u &#xE1;p d&#x1EE5;ng c&#xE1;c ti&#xEA;u chu&#x1EA9;n b&#x1EA3;o m&#x1EAD;t cao nh&#x1EA5;t. N&#x1EBF;u m&#x1ED9;t b&#x1B0;&#x1EDB;c n&#xE0;o &#x111;&#xF3; b&#x1ECB; y&#x1EBF;u th&#xEC; s&#x1EBD; g&#xE2;y nguy hi&#x1EC3;m cho c&#x1EA3; h&#x1EC7; th&#x1ED1;ng.</p><p>Ngo&#xE0;i ra, ch&#xFA;ng t&#xF4;i c&#x169;ng x&#xE2;y d&#x1EF1;ng c&#xE1;c h&#x1EC7; th&#x1ED1;ng ph&#xE1;t hi&#x1EC7;n v&#xE0; c&#x1EA3;nh b&#xE1;o b&#x1EA3;o m&#x1EAD;t m&#x1ED9;t c&#xE1;ch k&#x1EF9; c&#xE0;ng theo c&#xE1;c ti&#xEA;u chu&#x1EA9;n cao nh&#x1EA5;t c&#x1EE7;a PCI-DSS. C&#xE1;c flow ph&#xE1;t tri&#x1EC3;n s&#x1EA3;n ph&#x1EA9;m, CI/CD hay infrastructure c&#x169;ng c&#x1EA7;n &#x111;&#x1B0;&#x1EE3;c xem x&#xE9;t m&#x1ED9;t c&#xE1;ch k&#x1EF9; l&#x1B0;&#x1EE1;ng t&#x1EA1;i &#x111;&#xE2;y.</p>]]></content:encoded></item><item><title><![CDATA[CICD - OCG's Challenging Products (P7)]]></title><description><![CDATA[<h2 id="fully-automated-cicd">Fully automated CICD</h2><p>Khi n&#xF3;i &#x111;&#x1EBF;n &quot;Fully Automated CI/CD&quot; (Continuous Integration/Continuous Deployment ho&#xE0;n to&#xE0;n t&#x1EF1; &#x111;&#x1ED9;ng), ch&#xFA;ng ta &#x111;ang nh&#xEC;n v&#xE0;o m&#x1ED9;t quy tr&#xEC;nh</p>]]></description><link>https://engineering.shopbase.com/cicd-ocgs-challenging-products-2024-p2/</link><guid isPermaLink="false">65bb1a8995b8649d9ab0383f</guid><category><![CDATA[cicd]]></category><category><![CDATA[unit-test]]></category><category><![CDATA[integration-test]]></category><category><![CDATA[e2e-test]]></category><category><![CDATA[automated]]></category><category><![CDATA[challenging-products]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Tue, 23 Jan 2024 04:14:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/cicd.svg" medium="image"/><content:encoded><![CDATA[<h2 id="fully-automated-cicd">Fully automated CICD</h2><img src="https://engineering.shopbase.com/content/images/2024/02/cicd.svg" alt="CICD - OCG&apos;s Challenging Products (P7)"><p>Khi n&#xF3;i &#x111;&#x1EBF;n &quot;Fully Automated CI/CD&quot; (Continuous Integration/Continuous Deployment ho&#xE0;n to&#xE0;n t&#x1EF1; &#x111;&#x1ED9;ng), ch&#xFA;ng ta &#x111;ang nh&#xEC;n v&#xE0;o m&#x1ED9;t quy tr&#xEC;nh t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a &#x111;&#x1EA7;y &#x111;&#x1EE7; t&#x1EEB; kh&#xE2;u t&#xED;ch h&#x1EE3;p m&#xE3; ngu&#x1ED3;n (CI) &#x111;&#x1EBF;n kh&#xE2;u tri&#x1EC3;n khai (CD), m&#xE0; kh&#xF4;ng c&#x1EA7;n s&#x1EF1; can thi&#x1EC7;p c&#x1EE7;a con ng&#x1B0;&#x1EDD;i.</p><p>Qu&#xE1; tr&#xEC;nh &#x111;&#xF3; bao g&#x1ED3;m:</p><ul><li>Continuous Integration (CI)<ul><li>T&#xED;ch H&#x1EE3;p M&#xE3; Ngu&#x1ED3;n T&#x1EF1; &#x110;&#x1ED9;ng: M&#x1ED7;i khi c&#xF3; s&#x1EF1; thay &#x111;&#x1ED5;i trong m&#xE3; ngu&#x1ED3;n (commits), h&#x1EC7; th&#x1ED1;ng CI t&#x1EF1; &#x111;&#x1ED9;ng t&#xED;ch h&#x1EE3;p m&#xE3; ngu&#x1ED3;n t&#x1EEB; c&#xE1;c nh&#xE1;nh kh&#xE1;c nhau. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p &#x111;&#x1EA3;m b&#x1EA3;o r&#x1EB1;ng m&#xE3; m&#x1EDB;i kh&#xF4;ng xung &#x111;&#x1ED9;t v&#x1EDB;i m&#xE3; hi&#x1EC7;n c&#xF3;.</li><li>Ki&#x1EC3;m Th&#x1EED; T&#x1EF1; &#x110;&#x1ED9;ng: Sau khi t&#xED;ch h&#x1EE3;p m&#xE3;, h&#x1EC7; th&#x1ED1;ng th&#x1EF1;c hi&#x1EC7;n c&#xE1;c b&#xE0;i ki&#x1EC3;m th&#x1EED; t&#x1EF1; &#x111;&#x1ED9;ng &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o r&#x1EB1;ng m&#xE3; m&#x1EDB;i kh&#xF4;ng l&#xE0;m h&#x1ECF;ng ch&#x1EE9;c n&#x103;ng hi&#x1EC7;n t&#x1EA1;i. C&#xE1;c b&#xE0;i ki&#x1EC3;m th&#x1EED; n&#xE0;y c&#xF3; th&#x1EC3; bao g&#x1ED3;m ki&#x1EC3;m tra &#x111;&#x1A1;n v&#x1ECB;, ki&#x1EC3;m tra t&#xED;ch h&#x1EE3;p v&#xE0; ki&#x1EC3;m tra h&#x1EC7; th&#x1ED1;ng.</li><li>B&#xE1;o C&#xE1;o T&#x1EF1; &#x110;&#x1ED9;ng: K&#x1EBF;t qu&#x1EA3; ki&#x1EC3;m th&#x1EED; v&#xE0; tr&#x1EA1;ng th&#xE1;i t&#xED;ch h&#x1EE3;p &#x111;&#x1B0;&#x1EE3;c b&#xE1;o c&#xE1;o t&#x1EF1; &#x111;&#x1ED9;ng, cung c&#x1EA5;p th&#xF4;ng tin chi ti&#x1EBF;t v&#x1EC1; t&#xEC;nh tr&#x1EA1;ng c&#x1EE7;a m&#xE3; ngu&#x1ED3;n. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p c&#xE1;c nh&#xE0; ph&#xE1;t tri&#x1EC3;n d&#x1EC5; d&#xE0;ng x&#xE1;c &#x111;&#x1ECB;nh c&#xE1;c v&#x1EA5;n &#x111;&#x1EC1; v&#xE0; kh&#x1EAF;c ph&#x1EE5;c ch&#xFA;ng.</li></ul></li><li>Continuous Deployment (CD)<ul><li>Tri&#x1EC3;n Khai T&#x1EF1; &#x110;&#x1ED9;ng: N&#x1EBF;u qu&#xE1; tr&#xEC;nh t&#xED;ch h&#x1EE3;p th&#xE0;nh c&#xF4;ng, h&#x1EC7; th&#x1ED1;ng CD t&#x1EF1; &#x111;&#x1ED9;ng tri&#x1EC3;n khai m&#xE3; ngu&#x1ED3;n l&#xEA;n m&#xF4;i tr&#x1B0;&#x1EDD;ng th&#x1EED; nghi&#x1EC7;m ho&#x1EB7;c s&#x1EA3;n xu&#x1EA5;t m&#xE0; kh&#xF4;ng c&#x1EA7;n s&#x1EF1; can thi&#x1EC7;p c&#x1EE7;a ng&#x1B0;&#x1EDD;i qu&#x1EA3;n tr&#x1ECB;. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p gi&#x1EA3;m thi&#x1EC3;u th&#x1EDD;i gian c&#x1EA7;n thi&#x1EBF;t &#x111;&#x1EC3; &#x111;&#x1B0;a c&#xE1;c t&#xED;nh n&#x103;ng m&#x1EDB;i ra th&#x1ECB; tr&#x1B0;&#x1EDD;ng.</li><li>Qu&#x1EA3;n L&#xFD; Phi&#xEA;n B&#x1EA3;n: H&#x1EC7; th&#x1ED1;ng theo d&#xF5;i v&#xE0; qu&#x1EA3;n l&#xFD; c&#xE1;c phi&#xEA;n b&#x1EA3;n, gi&#xFA;p d&#x1EC5; d&#xE0;ng quay l&#x1EA1;i phi&#xEA;n b&#x1EA3;n tr&#x1B0;&#x1EDB;c &#x111;&#xF3; n&#x1EBF;u c&#xF3; v&#x1EA5;n &#x111;&#x1EC1; ph&#xE1;t sinh. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p &#x111;&#x1EA3;m b&#x1EA3;o t&#xED;nh &#x1ED5;n &#x111;&#x1ECB;nh c&#x1EE7;a h&#x1EC7; th&#x1ED1;ng.</li><li>Rollback T&#x1EF1; &#x110;&#x1ED9;ng: Trong tr&#x1B0;&#x1EDD;ng h&#x1EE3;p x&#x1EA5;u nh&#x1EA5;t, n&#x1EBF;u c&#xF3; s&#x1EF1; c&#x1ED1;, qu&#xE1; tr&#xEC;nh tri&#x1EC3;n khai t&#x1EF1; &#x111;&#x1ED9;ng c&#xF3; th&#x1EC3; &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EA3;o ng&#x1B0;&#x1EE3;c &#x111;&#x1EC3; quay v&#x1EC1; phi&#xEA;n b&#x1EA3;n tr&#x1B0;&#x1EDB;c &#x111;&#xF3;. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p gi&#x1EA3;m thi&#x1EC3;u th&#x1EDD;i gian ng&#x1EEB;ng ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a h&#x1EC7; th&#x1ED1;ng.</li></ul></li></ul><p>OCG &#x111;ang release s&#x1EA3;n ph&#x1EA9;m c&#x1EE7;a m&#xEC;nh theo c&#xE1;c chu k&#x1EF3; kho&#x1EA3;ng 2 - 4 tu&#x1EA7;n/l&#x1EA7;n. M&#x1ED7;i qu&#xE1; tr&#xEC;nh n&#xE0;y &#x111;&#xF2;i h&#x1ECF;i r&#x1EA5;t nhi&#x1EC1;u c&#xF4;ng t&#x1EEB; vi&#x1EC7;c build, deploy c&#xE1;c services, test features&#x2026;</p><p>OCG &#x111;ang h&#x1B0;&#x1EDB;ng t&#x1EDB;i vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng CICD t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a nh&#x1EB1;m gi&#x1EA3;m thi&#x1EC3;u t&#x1ED1;i &#x111;a c&#xF4;ng s&#x1EE9;c c&#x1EE7;a product team v&#xE0; time-to-market c&#x1EE7;a c&#xE1;c features. &#x110;i&#x1EC1;u n&#xE0;y s&#x1EBD; gi&#xFA;p OCG:</p><ul><li>T&#x103;ng t&#x1ED1;c &#x111;&#x1ED9; ph&#xE1;t tri&#x1EC3;n s&#x1EA3;n ph&#x1EA9;m</li><li>Gi&#x1EA3;m thi&#x1EC3;u l&#x1ED7;i</li><li>T&#x103;ng t&#xED;nh &#x1ED5;n &#x111;&#x1ECB;nh c&#x1EE7;a h&#x1EC7; th&#x1ED1;ng</li><li>Ti&#x1EBF;t ki&#x1EC7;m chi ph&#xED;</li></ul><p>H&#x1EC7; th&#x1ED1;ng n&#xE0;y &#x111;&#xF2;i h&#x1ECF;i Devops team ph&#x1EA3;i l&#xE0;m vi&#x1EC7;c r&#x1EA5;t s&#xE2;u s&#xE1;t v&#x1EDB;i product team, trong &#x111;&#xF3; c&#xF3; QE (Quality Engineer) team &#x111;&#x1EC3; qu&#x1EA3;n l&#xFD; &#x111;&#x1B0;&#x1EE3;c k&#x1EBF;t qu&#x1EA3; ch&#x1EA1;y test (ki&#x1EC3;m th&#x1EED;) feature v&#xE0; to&#xE0;n b&#x1ED9; s&#x1EA3;n ph&#x1EA9;m, qu&#x1EA3;n l&#xFD; c&#xE1;c phi&#xEA;n b&#x1EA3;n v&#xE0; c&#xF3; &#x111;&#x1EA7;y &#x111;&#x1EE7; c&#xF4;ng c&#x1EE5; monitor h&#x1EC7; th&#x1ED1;ng, performance, log, alert&#x2026;</p><p>&#x110;&#x1EC3; x&#xE2;y d&#x1EF1;ng th&#xE0;nh c&#xF4;ng h&#x1EC7; th&#x1ED1;ng CICD t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a, OCG c&#x1EA7;n:</p><ul><li>Chu&#x1EA9;n h&#xF3;a quy tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n s&#x1EA3;n ph&#x1EA9;m</li><li>X&#xE2;y d&#x1EF1;ng c&#xE1;c c&#xF4;ng c&#x1EE5; v&#xE0; quy tr&#xEC;nh t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a</li><li>T&#x1EAD;p hu&#x1EA5;n cho c&#xE1;c k&#x1EF9; s&#x1B0;</li></ul><p>OCG tin r&#x1EB1;ng vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng CICD t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a s&#x1EBD; gi&#xFA;p OCG n&#xE2;ng cao n&#x103;ng l&#x1EF1;c c&#x1EA1;nh tranh v&#xE0; mang l&#x1EA1;i tr&#x1EA3;i nghi&#x1EC7;m t&#x1ED1;t h&#x1A1;n cho ng&#x1B0;&#x1EDD;i d&#xF9;ng.</p>]]></content:encoded></item><item><title><![CDATA[Scaled KV Storage - OCG's Challenging Products (P5)]]></title><description><![CDATA[<h2 id="manage-assets-at-scalecost-optimization">&#xA0;Manage Assets at Scale - Cost Optimization</h2><p>Vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng c&#xE1;c n&#x1EC1;n t&#x1EA3;ng cloud (AWS, GCP, Azure...) gi&#xFA;p &#x111;&#x1A1;n gi&#x1EA3;n h&#xF3;a r&#x1EA5;t nhi&#x1EC1;u trong vi&#x1EC7;</p>]]></description><link>https://engineering.shopbase.com/ocgs-challenging-products-2024-p2-2/</link><guid isPermaLink="false">65bb19e895b8649d9ab0381e</guid><category><![CDATA[challenging-products]]></category><category><![CDATA[kv-storage]]></category><category><![CDATA[performance]]></category><category><![CDATA[scalability]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Sun, 21 Jan 2024 04:12:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/nebula-reading-storage-architecture.png" medium="image"/><content:encoded><![CDATA[<h2 id="manage-assets-at-scalecost-optimization">&#xA0;Manage Assets at Scale - Cost Optimization</h2><img src="https://engineering.shopbase.com/content/images/2024/02/nebula-reading-storage-architecture.png" alt="Scaled KV Storage - OCG&apos;s Challenging Products (P5)"><p>Vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng c&#xE1;c n&#x1EC1;n t&#x1EA3;ng cloud (AWS, GCP, Azure...) gi&#xFA;p &#x111;&#x1A1;n gi&#x1EA3;n h&#xF3;a r&#x1EA5;t nhi&#x1EC1;u trong vi&#x1EC7;c v&#x1EAD;n h&#xE0;nh s&#x1EA3;n ph&#x1EA9;m. B&#x1EDF;i OCG x&#xE2;y d&#x1EF1;ng s&#x1EA3;n ph&#x1EA9;m cho th&#x1ECB; tr&#x1B0;&#x1EDD;ng qu&#x1ED1;c t&#x1EBF; n&#xEA;n ch&#xFA;ng t&#xF4;i x&#xE1;c &#x111;&#x1ECB;nh s&#x1EA3;n ph&#x1EA9;m s&#x1EBD; g&#x1EAF;n li&#x1EC1;n v&#x1EDB;i c&#xE1;c n&#x1EC1;n t&#x1EA3;ng n&#xE0;y. B&#xEA;n c&#x1EA1;nh &#x111;&#xF3;, vi&#x1EC7;c s&#x1EED; d&#x1EE5;ng cloud c&#x169;ng mang &#x111;&#x1EBF;n kh&#xE1; nhi&#x1EC1;u b&#xE0;i to&#xE1;n c&#x1EA7;n t&#x1ED1;i &#x1B0;u h&#xF3;a chi ph&#xED; v&#xE0; qu&#x1EA3;n l&#xFD; resource t&#x1ED1;t h&#x1A1;n, trong &#x111;&#xF3; c&#xF3; b&#xE0;i to&#xE1;n qu&#x1EA3;n l&#xFD; t&#xE0;i nguy&#xEA;n &#x1EDF; quy m&#xF4; l&#x1EDB;n.</p><p>M&#x1ED7;i b&#x1EE9;c &#x1EA3;nh, ho&#x1EB7;c file ng&#x1B0;&#x1EDD;i d&#xF9;ng upload v&#xE0;o h&#x1EC7; th&#x1ED1;ng hi&#x1EC7;n t&#x1EA1;i &#x111;&#x1EC1;u &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u tr&#x1EEF; v&#xE0; qu&#x1EA3;n l&#xFD; tr&#x1EF1;c ti&#x1EBF;p tr&#xEA;n Cloud Storage v&#xE0; database. ShopBase hi&#x1EC7;n t&#x1EA1;i c&#xF3; t&#x1EDB;i h&#xE0;ng t&#x1EC9; files &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u tr&#x1EEF; tr&#xEA;n c&#xE1;c n&#x1EC1;n t&#x1EA3;ng &#x111;&#xF3;. Tuy v&#x1EAD;y, t&#xED;nh n&#x103;ng c&#x1EE7;a c&#xE1;c h&#x1EC7; th&#x1ED1;ng n&#xE0;y l&#x1EA1;i kh&#xE1; h&#x1EA1;n ch&#x1EBF;. C&#xF3; b&#xEA;n ch&#x1EC9; cho ph&#xE9;p x&#xF3;a c&#xE1;c files kh&#xF4;ng s&#x1EED; d&#x1EE5;ng &#x111;&#x1EBF;n sau m&#x1ED9;t kho&#x1EA3;ng th&#x1EDD;i gian x&#xE1;c &#x111;&#x1ECB;nh, c&#xF3; b&#xEA;n l&#x1EA1;i t&#xED;nh chi ph&#xED; call API r&#x1EA5;t cao.</p><p>&#x110;&#x1EC3; t&#x1ED1;i &#x1B0;u &#x111;&#x1B0;&#x1EE3;c chi ph&#xED;, v&#xE0; c&#xF3; th&#x1EC3; l&#x1B0;u tr&#x1EEF; tr&#xEA;n multi-cloud ch&#x1EC9; c&#xF3; m&#x1ED9;t c&#xE1;ch &#x111;&#xF3; l&#xE0; x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng &#x111;&#x1EC3; manage l&#x1B0;&#x1EE3;ng d&#x1EEF; li&#x1EC7;u &#x111;&#xF3; tr&#xEA;n n&#x1EC1;n c&#xE1;c c&#xF4;ng c&#x1EE5; l&#x1B0;u tr&#x1EEF; &#x111;&#xE1;m m&#xE2;y. H&#x1EC7; th&#x1ED1;ng n&#xE0;y s&#x1EBD; c&#x1EA7;n &#x111;&#x1EE7; nhanh &#x111;&#x1EC3; c&#xF3; th&#x1EC3; tr&#x1EA3; l&#x1EA1;i d&#x1EEF; li&#x1EC7;u cho ng&#x1B0;&#x1EDD;i d&#xF9;ng &#x1EDF; latency ph&#xF9; h&#x1EE3;p, c&#x1EA7;n c&#xF3; c&#xE1;c c&#x1A1; ch&#x1EBF; qu&#x1EA3;n l&#xFD; &#x111;&#x1EC3; c&#xF3; th&#x1EC3; x&#x1EED; l&#xFD; &#x111;&#x1B0;&#x1EE3;c c&#xE1;c b&#xE0;i to&#xE1;n: th&#xEA;m, s&#x1EED;a, x&#xF3;a, ghi nh&#x1EAD;n traffic, t&#x1EF1; &#x111;&#x1ED9;ng t&#x1ED1;i &#x1B0;u chi ph&#xED; theo c&#xE1;c rules c&#xF3; s&#x1EB5;n, th&#x1ED1;ng k&#xEA;, ch&#x1ED1;ng ddos, hot linking&#x2026; m&#xE0; kh&#xF4;ng &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n t&#x1ED1;c &#x111;&#x1ED9; truy xu&#x1EA5;t.</p><p>D&#x1B0;&#x1EDB;i &#x111;&#xE2;y l&#xE0; m&#x1ED9;t s&#x1ED1; th&#xE1;ch th&#x1EE9;c c&#x1EA7;n gi&#x1EA3;i quy&#x1EBF;t khi x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng n&#xE0;y:</p><ul><li>T&#x1ED1;c &#x111;&#x1ED9;: H&#x1EC7; th&#x1ED1;ng c&#x1EA7;n c&#xF3; kh&#x1EA3; n&#x103;ng x&#x1EED; l&#xFD; truy v&#x1EA5;n d&#x1EEF; li&#x1EC7;u nhanh ch&#xF3;ng, &#x111;&#xE1;p &#x1EE9;ng &#x111;&#x1B0;&#x1EE3;c nhu c&#x1EA7;u c&#x1EE7;a ng&#x1B0;&#x1EDD;i d&#xF9;ng.</li><li>Qu&#x1EA3;n l&#xFD;: H&#x1EC7; th&#x1ED1;ng c&#x1EA7;n c&#xF3; c&#xE1;c c&#x1A1; ch&#x1EBF; qu&#x1EA3;n l&#xFD; ch&#x1EB7;t ch&#x1EBD; &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o an to&#xE0;n d&#x1EEF; li&#x1EC7;u v&#xE0; t&#x1ED1;i &#x1B0;u h&#xF3;a chi ph&#xED;.</li><li>Kh&#x1EA3; n&#x103;ng m&#x1EDF; r&#x1ED9;ng: H&#x1EC7; th&#x1ED1;ng c&#x1EA7;n c&#xF3; kh&#x1EA3; n&#x103;ng m&#x1EDF; r&#x1ED9;ng &#x111;&#x1EC3; &#x111;&#xE1;p &#x1EE9;ng nhu c&#x1EA7;u t&#x103;ng tr&#x1B0;&#x1EDF;ng d&#x1EEF; li&#x1EC7;u trong t&#x1B0;&#x1A1;ng lai.</li></ul><p>&#x110;&#x1EC3; gi&#x1EA3;i quy&#x1EBF;t nh&#x1EEF;ng th&#xE1;ch th&#x1EE9;c n&#xE0;y, OCG mong mu&#x1ED1;n c&#xE1;c b&#x1EA1;n c&#xF3; hi&#x1EC3;u bi&#x1EBF;t s&#xE2;u s&#x1EAF;c v&#x1EC1; c&#xE1;c c&#xF4;ng ngh&#x1EC7; l&#x1B0;u tr&#x1EEF; NoSQL, SQL, c&#x169;ng nh&#x1B0; c&#xE1;c ki&#x1EBF;n th&#x1EE9;c v&#x1EC1; h&#x1EC7; th&#x1ED1;ng ph&#xE2;n t&#xE1;n, big data, machine learning nh&#x1EB1;m x&#xE2;y d&#x1EF1;ng &#x111;&#x1B0;&#x1EE3;c h&#x1EC7; th&#x1ED1;ng n&#xE0;y m&#x1ED9;t c&#xE1;ch t&#x1ED1;i &#x1B0;u nh&#x1EA5;t.</p>]]></content:encoded></item><item><title><![CDATA[Automated Infrastructure - OCG's Challenging Products (P6)]]></title><description><![CDATA[<h2 id="automated-infrastructure-infra-as-code">Automated infrastructure (Infra-as-code)</h2><p>Sau nhi&#x1EC1;u n&#x103;m v&#x1EAD;n h&#xE0;nh h&#x1EC7; th&#x1ED1;ng, t&#x1EEB; c&#xE1;c s&#x1EA3;n ph&#x1EA9;m Beeketing t&#x1EDB;i ShopBase, OCG &#x111;&#xE3; &#x111;&#xFA;c k&#x1EBF;t &#x111;&#x1B0;&#x1EE3;c</p>]]></description><link>https://engineering.shopbase.com/ocgs-challenging-products-2024-p6/</link><guid isPermaLink="false">65bb1a3295b8649d9ab03829</guid><category><![CDATA[challenging-products]]></category><category><![CDATA[infrastructure]]></category><category><![CDATA[automated]]></category><category><![CDATA[cicd]]></category><category><![CDATA[cost-optimization]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Tue, 16 Jan 2024 04:13:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/1_KjJ9qJdi2gox6edmrBSCUg.webp" medium="image"/><content:encoded><![CDATA[<h2 id="automated-infrastructure-infra-as-code">Automated infrastructure (Infra-as-code)</h2><img src="https://engineering.shopbase.com/content/images/2024/02/1_KjJ9qJdi2gox6edmrBSCUg.webp" alt="Automated Infrastructure - OCG&apos;s Challenging Products (P6)"><p>Sau nhi&#x1EC1;u n&#x103;m v&#x1EAD;n h&#xE0;nh h&#x1EC7; th&#x1ED1;ng, t&#x1EEB; c&#xE1;c s&#x1EA3;n ph&#x1EA9;m Beeketing t&#x1EDB;i ShopBase, OCG &#x111;&#xE3; &#x111;&#xFA;c k&#x1EBF;t &#x111;&#x1B0;&#x1EE3;c m&#x1ED9;t kinh nghi&#x1EC7;m r&#x1EA5;t quan tr&#x1ECD;ng &#x111;&#xF3; l&#xE0; &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o &#x111;&#x1B0;&#x1EE3;c h&#x1EC7; th&#x1ED1;ng &#x1ED5;n &#x111;&#x1ECB;nh, infrastructure c&#x1EA7;n &#x111;&#x1B0;&#x1EE3;c x&#xE2;y d&#x1EF1;ng v&#xE0; maintain m&#x1ED9;t c&#xE1;ch t&#x1EF1; &#x111;&#x1ED9;ng.</p><p>H&#x1EC7; th&#x1ED1;ng h&#x1EA1; t&#x1EA7;ng l&#xE0; n&#x1EC1;n t&#x1EA3;ng cho m&#x1ECD;i ho&#x1EA1;t &#x111;&#x1ED9;ng c&#x1EE7;a m&#x1ED9;t doanh nghi&#x1EC7;p. N&#xF3; bao g&#x1ED3;m c&#xE1;c y&#x1EBF;u t&#x1ED1; nh&#x1B0; m&#xE1;y ch&#x1EE7;, m&#x1EA1;ng, l&#x1B0;u tr&#x1EEF;, b&#x1EA3;o m&#x1EAD;t,... Vi&#x1EC7;c v&#x1EAD;n h&#xE0;nh h&#x1EC7; th&#x1ED1;ng h&#x1EA1; t&#x1EA7;ng th&#x1EE7; c&#xF4;ng &#x111;&#xF2;i h&#x1ECF;i nhi&#x1EC1;u th&#x1EDD;i gian v&#xE0; c&#xF4;ng s&#x1EE9;c, &#x111;&#x1ED3;ng th&#x1EDD;i d&#x1EC5; d&#x1EAB;n &#x111;&#x1EBF;n sai s&#xF3;t.</p><p>T&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a h&#x1EA1; t&#x1EA7;ng (Infra-as-code) l&#xE0; gi&#x1EA3;i ph&#xE1;p gi&#xFA;p gi&#x1EA3;i quy&#x1EBF;t nh&#x1EEF;ng v&#x1EA5;n &#x111;&#x1EC1; n&#xE0;y. V&#x1EDB;i Infra-as-code, c&#xE1;c c&#x1EA5;u h&#xEC;nh h&#x1EA1; t&#x1EA7;ng &#x111;&#x1B0;&#x1EE3;c th&#x1EC3; hi&#x1EC7;n d&#x1B0;&#x1EDB;i d&#x1EA1;ng code, thay v&#xEC; th&#x1EF1;c hi&#x1EC7;n th&#x1EE7; c&#xF4;ng b&#x1EB1;ng giao di&#x1EC7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p vi&#x1EC7;c x&#xE2;y d&#x1EF1;ng, qu&#x1EA3;n l&#xFD; v&#xE0; v&#x1EAD;n h&#xE0;nh h&#x1EC7; th&#x1ED1;ng h&#x1EA1; t&#x1EA7;ng tr&#x1EDF; n&#xEA;n &#x111;&#x1A1;n gi&#x1EA3;n, hi&#x1EC7;u qu&#x1EA3; v&#xE0; an to&#xE0;n h&#x1A1;n.</p><p>T&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a h&#x1EA1; t&#x1EA7;ng mang l&#x1EA1;i nhi&#x1EC1;u &#x1B0;u &#x111;i&#x1EC3;m cho doanh nghi&#x1EC7;p, bao g&#x1ED3;m:</p><ul><li>Hi&#x1EC7;u qu&#x1EA3;: T&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a gi&#xFA;p t&#x103;ng c&#x1B0;&#x1EDD;ng hi&#x1EC7;u su&#x1EA5;t v&#xE0; gi&#x1EA3;m th&#x1EDD;i gian tri&#x1EC3;n khai, gi&#xFA;p doanh nghi&#x1EC7;p nhanh ch&#xF3;ng &#x111;&#xE1;p &#x1EE9;ng c&#xE1;c y&#xEA;u c&#x1EA7;u m&#x1EDB;i. &#x110;&#x1EB7;c bi&#x1EC7;t, c&#xE1;c devops teams v&#x1EAD;n h&#xE0;nh s&#x1EBD; r&#x1EA5;t nhanh ch&#xF3;ng: training ng&#x1B0;&#x1EDD;i m&#x1EDB;i, monitor c&#xE1;c thay &#x111;&#x1ED5;i, qu&#x1EA3;n l&#xFD; resources, t&#x1ED1;i &#x1B0;u chi ph&#xED;&#x2026;</li><li>Minh b&#x1EA1;ch: H&#x1EC7; th&#x1ED1;ng t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a cung c&#x1EA5;p d&#x1EEF; li&#x1EC7;u minh b&#x1EA1;ch v&#xE0; chi ti&#x1EBF;t, gi&#xFA;p theo d&#xF5;i v&#xE0; ph&#xE2;n t&#xED;ch hi&#x1EC7;u su&#x1EA5;t h&#x1EC7; th&#x1ED1;ng.</li><li>Gi&#x1EA3;m sai s&#x1ED1;: Lo&#x1EA1;i b&#x1ECF; sai s&#xF3;t do con ng&#x1B0;&#x1EDD;i, l&#xE0;m gi&#x1EA3;m nguy c&#x1A1; s&#x1EF1; c&#x1ED1; v&#xE0; t&#x103;ng t&#xED;nh &#x1ED5;n &#x111;&#x1ECB;nh c&#x1EE7;a c&#x1A1; s&#x1EDF; h&#x1EA1; t&#x1EA7;ng.</li><li>T&#x103;ng t&#xED;nh b&#x1EA3;o m&#x1EAD;t cho h&#x1EC7; th&#x1ED1;ng: T&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a gi&#xFA;p gi&#x1EA3;m thi&#x1EC3;u c&#xE1;c l&#x1ED7; h&#x1ED5;ng b&#x1EA3;o m&#x1EAD;t do con ng&#x1B0;&#x1EDD;i g&#xE2;y ra.</li></ul><p>OCG &#x111;&#xE3; x&#xE2;y d&#x1EF1;ng &#x111;&#x1B0;&#x1EE3;c m&#x1ED9;t s&#x1ED1; t&#xED;nh n&#x103;ng ch&#xED;nh cho h&#x1EC7; th&#x1ED1;ng Infra-as-code, tuy nhi&#xEA;n, v&#x1EAB;n c&#xF2;n nhi&#x1EC1;u c&#xE1;c th&#xE0;nh ph&#x1EA7;n, t&#xED;nh n&#x103;ng trong danh s&#xE1;ch tr&#xEA;n v&#x1EAB;n c&#x1EA7;n &#x111;&#x1B0;&#x1EE3;c b&#x1ED5; sung v&#xE0;o h&#x1EC7; th&#x1ED1;ng &#x111;&#x1EC3; &#x111;&#x1A1;n gi&#x1EA3;n h&#xF3;a qu&#xE1; tr&#xEC;nh v&#x1EAD;n h&#xE0;nh h&#x1A1;n n&#x1EEF;a.</p><p>Ng&#x1B0;&#x1EDD;i x&#xE2;y d&#x1EF1;ng s&#x1EA3;n ph&#x1EA9;m Infra-as-code kh&#xF4;ng ch&#x1EC9; &#x111;&#xF2;i h&#x1ECF;i c&#xE1;c ki&#x1EBF;n th&#x1EE9;c s&#xE2;u v&#x1EC1; h&#x1EA1; t&#x1EA7;ng, t&#x1B0;&#x1A1;ng t&#xE1;c v&#x1EDB;i c&#xE1;c n&#x1EC1;n t&#x1EA3;ng Cloud, m&#xE0; c&#xF2;n ph&#x1EA3;i hi&#x1EC3;u r&#x1EA5;t s&#xE2;u v&#x1EC1; c&#xE1;ch ShopBase system ho&#x1EA1;t &#x111;&#x1ED9;ng &#x111;&#x1EC3; c&#xF3; th&#x1EC3; thi&#x1EBF;t k&#x1EBF; v&#xE0; ho&#xE0;n thi&#x1EC7;n &#x111;&#x1B0;&#x1EE3;c h&#x1EC7; th&#x1ED1;ng Infra-as-code t&#x1EA1;i OCG.</p>]]></content:encoded></item><item><title><![CDATA[AI - OCG's Challenging Products 2024 (P4)]]></title><description><![CDATA[<h2 id="printbasean-ai-powered-product">PrintBase - An AI-Powered Product</h2><figure class="kg-card kg-image-card"><img src="https://assets-global.website-files.com/5ed4c2a86103a3136bf1e97c/60c0b76b66ba29388fca7fba_PlusBase%20Logo%20Dark%20Color-2.png" class="kg-image" alt="PrintBase | Product Catalog" loading="lazy"></figure><p>PrintBase l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng s&#x1EA3;n ph&#x1EA9;m th&#xE0;nh c&#xF4;ng nh&#x1EA5;t c&#x1EE7;a OCG v&#xE0; h&#x1EC7; sinh th&#xE1;i ShopBase. H&#x1B0;&#x1EDB;ng &#x111;&#x1EBF;n</p>]]></description><link>https://engineering.shopbase.com/ai-ocgs-challenging-products-2024-p4/</link><guid isPermaLink="false">65bb19af95b8649d9ab03805</guid><category><![CDATA[challenging-products]]></category><category><![CDATA[printbase]]></category><category><![CDATA[image]]></category><category><![CDATA[ai]]></category><category><![CDATA[artificial-intelligent]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Fri, 12 Jan 2024 04:10:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1620712943543-bcc4688e7485?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fEFJJTIwZm9yJTIwZS1jb21tZXJjZXxlbnwwfHx8fDE3MDY3NjMxMDB8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h2 id="printbasean-ai-powered-product">PrintBase - An AI-Powered Product</h2><figure class="kg-card kg-image-card"><img src="https://assets-global.website-files.com/5ed4c2a86103a3136bf1e97c/60c0b76b66ba29388fca7fba_PlusBase%20Logo%20Dark%20Color-2.png" class="kg-image" alt="AI - OCG&apos;s Challenging Products 2024 (P4)" loading="lazy"></figure><img src="https://images.unsplash.com/photo-1620712943543-bcc4688e7485?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fEFJJTIwZm9yJTIwZS1jb21tZXJjZXxlbnwwfHx8fDE3MDY3NjMxMDB8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="AI - OCG&apos;s Challenging Products 2024 (P4)"><p>PrintBase l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng s&#x1EA3;n ph&#x1EA9;m th&#xE0;nh c&#xF4;ng nh&#x1EA5;t c&#x1EE7;a OCG v&#xE0; h&#x1EC7; sinh th&#xE1;i ShopBase. H&#x1B0;&#x1EDB;ng &#x111;&#x1EBF;n th&#x1ECB; tr&#x1B0;&#x1EDD;ng Print-On-Demand (POD), PrintBase cung c&#x1EA5;p gi&#x1EA3;i ph&#xE1;p &#x111;&#x1A1;n gi&#x1EA3;n h&#xF3;a nhi&#x1EC1;u b&#x1B0;&#x1EDB;c trong vi&#x1EC7;c b&#xE1;n h&#xE0;ng POD, t&#x1EEB; x&#x1EED; l&#xFD; mockup, artwork &#x111;&#x1EBF;n c&#xE0;i &#x111;&#x1EB7;t, &#x111;&#x103;ng k&#xFD; c&#x1ED5;ng thanh to&#xE1;n, l&#xE0;m vi&#x1EC7;c v&#x1EDB;i nh&#xE0; cung c&#x1EA5;p, ch&#x103;m s&#xF3;c kh&#xE1;ch h&#xE0;ng v&#xE0; ship s&#x1EA3;n ph&#x1EA9;m &#x111;&#x1EBF;n cho ng&#x1B0;&#x1EDD;i mua.</p><p>G&#x1EA7;n &#x111;&#xE2;y, xu h&#x1B0;&#x1EDB;ng &#xE1;p d&#x1EE5;ng AI v&#xE0;o s&#x1EA3;n ph&#x1EA9;m kh&#xF4;ng c&#xF2;n xa l&#x1EA1; v&#x1EDB;i c&#x1ED9;ng &#x111;&#x1ED3;ng ph&#x1EA7;n m&#x1EC1;m. Tuy nhi&#xEA;n, &#x111;&#x1EC3; AI c&#xF3; th&#x1EC3; t&#x1EA1;o ra s&#x1EA3;n ph&#x1EA9;m ph&#xF9; h&#x1EE3;p v&#x1EDB;i ng&#x1B0;&#x1EDD;i d&#xF9;ng trong th&#x1ECB; tr&#x1B0;&#x1EDD;ng e-commerce l&#xE0; m&#x1ED9;t &#x111;i&#x1EC1;u kh&#xE1; kh&#xF3;. Nhu c&#x1EA7;u c&#x1EE7;a ng&#x1B0;&#x1EDD;i s&#x1EED; d&#x1EE5;ng v&#x1EDB;i c&#xE1;c s&#x1EA3;n ph&#x1EA9;m in &#x1EA5;n ph&#x1EE5; thu&#x1ED9;c v&#xE0;o r&#x1EA5;t nhi&#x1EC1;u y&#x1EBF;u t&#x1ED1;: v&#x103;n h&#xF3;a v&#xF9;ng mi&#x1EC1;n, ng&#xF4;n ng&#x1EEF;, xu h&#x1B0;&#x1EDB;ng hi&#x1EC7;n t&#x1EA1;i c&#x1EE7;a th&#x1ECB; tr&#x1B0;&#x1EDD;ng&#x2026;</p><p>B&#x1EB1;ng c&#xE1;ch t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a qu&#xE1; tr&#xEC;nh t&#x1EA1;o ra thi&#x1EBF;t k&#x1EBF;, n&#x1ED9;i dung v&#xE0; x&#xE1;c &#x111;&#x1ECB;nh &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng m&#x1EE5;c ti&#xEA;u, AI c&#xF3; th&#x1EC3; gi&#xFA;p PrintBase:</p><ul><li>Gi&#x1EA3;m th&#x1EDD;i gian v&#xE0; c&#xF4;ng s&#x1EE9;c c&#x1EA7;n thi&#x1EBF;t cho c&#xE1;c nh&#xE0; b&#xE1;n l&#x1EBB; &#x111;&#x1EC3; b&#xE1;n c&#xE1;c s&#x1EA3;n ph&#x1EA9;m POD</li><li>C&#x1EA3;i thi&#x1EC7;n ch&#x1EA5;t l&#x1B0;&#x1EE3;ng s&#x1EA3;n ph&#x1EA9;m v&#xE0; n&#x1ED9;i dung</li><li>M&#x1EDF; r&#x1ED9;ng ph&#x1EA1;m vi ti&#x1EBF;p c&#x1EAD;n c&#x1EE7;a s&#x1EA3;n ph&#x1EA9;m &#x111;&#x1EBF;n nhi&#x1EC1;u &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng h&#x1A1;n</li></ul><p>&#x110;&#x1EC3; PrintBase cung c&#x1EA5;p d&#x1ECB;ch v&#x1EE5; m&#x1EA1;nh h&#x1A1;n n&#x1EEF;a, t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a g&#x1EA7;n nh&#x1B0; ho&#xE0;n to&#xE0;n qu&#xE1; tr&#xEC;nh b&#xE1;n h&#xE0;ng POD, OCG d&#x1EF1; &#x111;&#x1ECB;nh s&#x1EBD; nghi&#xEA;n c&#x1EE9;u v&#xE0; &#xE1;p d&#x1EE5;ng c&#xE1;c m&#xF4; h&#xEC;nh AI &#x111;&#x1EC3; t&#x1EA1;o ra c&#xE1;c thi&#x1EBF;t k&#x1EBF; c&#x1EE7;a s&#x1EA3;n ph&#x1EA9;m in, t&#x1EA1;o ra c&#xE1;c content ph&#xF9; h&#x1EE3;p, h&#x1EA5;p d&#x1EAB;n &#x111;&#x1EC3; t&#x103;ng t&#xED;nh h&#x1EA5;p d&#x1EAB;n cho s&#x1EA3;n ph&#x1EA9;m, x&#xE1;c &#x111;&#x1ECB;nh &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng ng&#x1B0;&#x1EDD;i mua h&#xE0;ng ph&#xF9; h&#x1EE3;p cho merchant. OCG &#x111;&#xE3; v&#xE0; &#x111;ang &#xE1;p d&#x1EE5;ng ChatGPT v&#xE0; Midjourney &#x111;&#x1EC3; x&#xE2;y d&#x1EF1;ng content cho m&#x1ED9;t s&#x1ED1; s&#x1EA3;n ph&#x1EA9;m. Tuy nhi&#xEA;n, khi &#xE1;p d&#x1EE5;ng &#x1EDF; m&#x1ED9;t scale l&#x1EDB;n l&#x1EA1;i l&#xE0; b&#xE0;i to&#xE1;n ho&#xE0;n to&#xE0;n kh&#xE1;c. X&#xE2;y d&#x1EF1;ng content v&#x1EC1; h&#xEC;nh &#x1EA3;nh l&#xE0; m&#x1ED9;t trong nh&#x1EEF;ng challenge r&#x1EA5;t kh&#xF3; v&#xE0; h&#x1EA5;p d&#x1EAB;n. OCG r&#x1EA5;t hy v&#x1ECD;ng 2024 l&#xE0; m&#x1ED9;t n&#x103;m &#x111;&#x1ED9;t ph&#xE1; v&#x1EC1; vi&#x1EC7;c &#xE1;p d&#x1EE5;ng AI v&#xE0;o s&#x1EA3;n ph&#x1EA9;m m&#x1ED9;t c&#xE1;ch to&#xE0;n di&#x1EC7;n.</p>]]></content:encoded></item><item><title><![CDATA[Sharding - OCG's Challenging Products (P7)]]></title><description><![CDATA[<h2 id="sharding-by-design">Sharding by design</h2><p>OCG t&#x1EF1; h&#xE0;o l&#xE0; c&#xF4;ng ty x&#xE2;y d&#x1EF1;ng &#x111;&#x1B0;&#x1EE3;c s&#x1EA3;n ph&#x1EA9;m trong th&#x1ECB; tr&#x1B0;&#x1EDD;ng qu&#x1ED1;c t&#x1EBF; c&#x1EF1;c k&#x1EF3; c&#x1EA1;</p>]]></description><link>https://engineering.shopbase.com/ocgs-challenging-products-2024-p2-3/</link><guid isPermaLink="false">65bb1a6195b8649d9ab03833</guid><category><![CDATA[challenging-products]]></category><category><![CDATA[shard]]></category><category><![CDATA[modularity]]></category><category><![CDATA[openresty]]></category><category><![CDATA[golang]]></category><category><![CDATA[vuejs]]></category><category><![CDATA[china]]></category><category><![CDATA[ai]]></category><category><![CDATA[app]]></category><dc:creator><![CDATA[William Truong]]></dc:creator><pubDate>Mon, 08 Jan 2024 04:13:00 GMT</pubDate><media:content url="https://engineering.shopbase.com/content/images/2024/02/0_buODpXLi3KFmCihY.webp" medium="image"/><content:encoded><![CDATA[<h2 id="sharding-by-design">Sharding by design</h2><img src="https://engineering.shopbase.com/content/images/2024/02/0_buODpXLi3KFmCihY.webp" alt="Sharding - OCG&apos;s Challenging Products (P7)"><p>OCG t&#x1EF1; h&#xE0;o l&#xE0; c&#xF4;ng ty x&#xE2;y d&#x1EF1;ng &#x111;&#x1B0;&#x1EE3;c s&#x1EA3;n ph&#x1EA9;m trong th&#x1ECB; tr&#x1B0;&#x1EDD;ng qu&#x1ED1;c t&#x1EBF; c&#x1EF1;c k&#x1EF3; c&#x1EA1;nh tranh. &#x110;i&#x1EC1;u &#x111;&#xF3; mang &#x111;&#x1EBF;n cho ch&#xFA;ng t&#xF4;i nh&#x1EEF;ng kh&#xF3; kh&#x103;n v&#xE0; c&#x1A1; h&#x1ED9;i r&#x1EA5;t l&#x1EDB;n. Ph&#x1EE5;c v&#x1EE5; kh&#xE1;ch h&#xE0;ng qu&#x1ED1;c t&#x1EBF; &#x1EDF; nhi&#x1EC1;u qu&#x1ED1;c gia, &#x111;&#x1EA3;m b&#x1EA3;o tr&#x1EA3;i nghi&#x1EC7;m ng&#x1B0;&#x1EDD;i d&#xF9;ng l&#xE0; m&#x1ED9;t b&#xE0;i to&#xE1;n c&#x1EF1;c k&#x1EF3; kh&#xF3; v&#xE0; t&#x1ED1;n k&#xE9;m kh&#xF4;ng ch&#x1EC9; v&#x1EDB;i OCG m&#xE0; v&#x1EDB;i b&#x1EA5;t k&#x1EF3; s&#x1EA3;n ph&#x1EA9;m, c&#xF4;ng ty n&#xE0;o. C&#xF3; r&#x1EA5;t nhi&#x1EC1;u challenges ph&#x1EA3;i gi&#x1EA3;i quy&#x1EBF;t nh&#x1B0;:</p><p>1. Ph&#xE2;n chia &#x111;&#x1B0;&#x1EE3;c c&#xE1;c &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng kh&#xE1;ch h&#xE0;ng ri&#xEA;ng bi&#x1EC7;t &#x1EDF; t&#x1EEB;ng c&#x1EE5;m servers kh&#xE1;c nhau, &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o tr&#x1EA3;i nghi&#x1EC7;m v&#x1EAD;n h&#xE0;nh &#x1ED5;n &#x111;&#x1ECB;nh. V&#xED; d&#x1EE5;: c&#xE1;c website/stores m&#x1EDB;i m&#x1EDF; s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c d&#x1EF1;ng &#x1EDF; m&#x1ED9;t c&#x1EE5;m server, c&#xE1;c website/stores &#x111;&#xE3; &#x1ED5;n &#x111;&#x1ECB;nh &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t &#x1EDF; m&#x1ED9;t c&#x1EE5;m server kh&#xE1;c.</p><p>&#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p &#x111;&#x1EA3;m b&#x1EA3;o r&#x1EB1;ng c&#xE1;c website/stores m&#x1EDB;i m&#x1EDF; s&#x1EBD; kh&#xF4;ng &#x1EA3;nh h&#x1B0;&#x1EDF;ng &#x111;&#x1EBF;n hi&#x1EC7;u su&#x1EA5;t c&#x1EE7;a c&#xE1;c website/stores &#x111;&#xE3; &#x1ED5;n &#x111;&#x1ECB;nh. V&#xED; d&#x1EE5;, n&#x1EBF;u m&#x1ED9;t website/stores m&#x1EDB;i m&#x1EDF; nh&#x1EAD;n &#x111;&#x1B0;&#x1EE3;c l&#x1B0;u l&#x1B0;&#x1EE3;ng truy c&#x1EAD;p l&#x1EDB;n &#x111;&#x1ED9;t ng&#x1ED9;t, &#x111;i&#x1EC1;u n&#xE0;y c&#xF3; th&#x1EC3; g&#xE2;y ra s&#x1EF1; c&#x1ED1; cho c&#xE1;c website/stores kh&#xE1;c. B&#x1EB1;ng c&#xE1;ch ph&#xE2;n chia c&#xE1;c website/stores th&#xE0;nh c&#xE1;c c&#x1EE5;m ri&#xEA;ng bi&#x1EC7;t, ch&#xFA;ng ta c&#xF3; th&#x1EC3; ki&#x1EC3;m so&#xE1;t l&#x1B0;u l&#x1B0;&#x1EE3;ng truy c&#x1EAD;p &#x111;&#x1EBF;n t&#x1EEB;ng c&#x1EE5;m m&#x1ED9;t c&#xE1;ch hi&#x1EC7;u qu&#x1EA3; h&#x1A1;n.</p><p>2. V&#x1EAD;n h&#xE0;nh &#x111;&#x1B0;&#x1EE3;c &#x1ED5;n &#x111;&#x1ECB;nh &#x1EDF; th&#x1ECB; tr&#x1B0;&#x1EDD;ng Trung Qu&#x1ED1;c (m&#x1ED9;t th&#x1ECB; tr&#x1B0;&#x1EDD;ng c&#x1EF1;c k&#x1EF3; kh&#xE1;c bi&#x1EC7;t v&#x1EDB;i c&#xE1;c s&#x1EA3;n ph&#x1EA9;m c&#xF4;ng ngh&#x1EC7; th&#xF4;ng tin). N&#x1EBF;u ai &#x111;&#xE3; deploy s&#x1EA3;n ph&#x1EA9;m cho th&#x1ECB; tr&#x1B0;&#x1EDD;ng trung qu&#x1ED1;c ch&#x1EAF;c ch&#x1EAF;n &#x111;&#xE3; g&#x1EB7;p r&#x1EA5;t nhi&#x1EC1;u v&#x1EA5;n &#x111;&#x1EC1; v&#x1EC1; traffic b&#x1ECB; ch&#x1EB7;n b&#x1EDF;i China Great Firewall, h&#x1EC7; th&#x1ED1;ng ch&#x1EE9;ng ch&#x1EC9; cho website trong n&#x1ED9;i &#x111;&#x1ECB;a Trung Qu&#x1ED1;c&#x2026;</p><p>&#x110;&#x1EC3; gi&#x1EA3;i quy&#x1EBF;t v&#x1EA5;n &#x111;&#x1EC1; n&#xE0;y, ch&#xFA;ng ta c&#x1EA7;n x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng c&#xF3; th&#x1EC3; v&#x1B0;&#x1EE3;t qua &#x111;&#x1B0;&#x1EE3;c c&#xE1;c h&#x1EA1;n ch&#x1EBF; c&#x1EE7;a th&#x1ECB; tr&#x1B0;&#x1EDD;ng Trung Qu&#x1ED1;c. V&#xED; d&#x1EE5;, ch&#xFA;ng ta c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng c&#xE1;c c&#xF4;ng ngh&#x1EC7; nh&#x1B0; VPN ho&#x1EB7;c proxy &#x111;&#x1EC3; truy c&#x1EAD;p v&#xE0;o c&#xE1;c website/stores t&#x1EEB; Trung Qu&#x1ED1;c. Ngo&#xE0;i ra, ch&#xFA;ng ta c&#x169;ng c&#x1EA7;n &#x111;&#x1EA3;m b&#x1EA3;o r&#x1EB1;ng c&#xE1;c website/stores c&#x1EE7;a m&#xEC;nh tu&#xE2;n th&#x1EE7; c&#xE1;c quy &#x111;&#x1ECB;nh c&#x1EE7;a th&#x1ECB; tr&#x1B0;&#x1EDD;ng Trung Qu&#x1ED1;c.</p><p>3. C&#xE1;c stores v&#x1EAD;n h&#xE0;nh &#x1EDF; Ch&#xE2;u &#xC2;u &#x111;&#x1B0;&#x1EE3;c thi&#x1EBF;t l&#x1EAD;p c&#xE1;c c&#x1A1; ch&#x1EBF;, ch&#x1EE9;ng ch&#x1EC9; ri&#xEA;ng &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o &#x111;&#x1B0;&#x1EE3;c y&#xEA;u c&#x1EA7;u kh&#x1EAF;t khe v&#x1EC1; quy&#x1EC1;n ri&#xEA;ng t&#x1B0;, b&#x1EA3;o m&#x1EAD;t c&#x1EE7;a h&#x1ECD;.</p><p>Ch&#xE2;u &#xC2;u c&#xF3; c&#xE1;c quy &#x111;&#x1ECB;nh v&#x1EC1; quy&#x1EC1;n ri&#xEA;ng t&#x1B0; v&#xE0; b&#x1EA3;o m&#x1EAD;t r&#x1EA5;t nghi&#xEA;m ng&#x1EB7;t. &#x110;&#x1EC3; tu&#xE2;n th&#x1EE7; c&#xE1;c quy &#x111;&#x1ECB;nh n&#xE0;y, ch&#xFA;ng ta c&#x1EA7;n x&#xE2;y d&#x1EF1;ng h&#x1EC7; th&#x1ED1;ng c&#xF3; th&#x1EC3; b&#x1EA3;o v&#x1EC7; d&#x1EEF; li&#x1EC7;u c&#x1EE7;a ng&#x1B0;&#x1EDD;i d&#xF9;ng. V&#xED; d&#x1EE5;, ch&#xFA;ng ta c&#xF3; th&#x1EC3; s&#x1EED; d&#x1EE5;ng c&#xE1;c c&#xF4;ng ngh&#x1EC7; nh&#x1B0; m&#xE3; h&#xF3;a d&#x1EEF; li&#x1EC7;u ho&#x1EB7;c c&#xE1;c c&#x1A1; ch&#x1EBF; x&#xE1;c th&#x1EF1;c hai y&#x1EBF;u t&#x1ED1;.</p><p>&#x110;&#x1EC3; gi&#x1EA3;i quy&#x1EBF;t nh&#x1EEF;ng challenges n&#xE0;y, ch&#xFA;ng t&#xF4;i mong mu&#x1ED1;n x&#xE2;y d&#x1EF1;ng m&#x1ED9;t h&#x1EC7; th&#x1ED1;ng s&#x1EA3;n ph&#x1EA9;m, infrastructure c&#xF3; th&#x1EC3; Shard By Design. Sharding by design l&#xE0; m&#x1ED9;t k&#x1EF9; thu&#x1EAD;t ph&#xE2;n v&#xF9;ng d&#x1EEF; li&#x1EC7;u v&#xE0; d&#x1ECB;ch v&#x1EE5; th&#xE0;nh c&#xE1;c c&#x1EE5;m nh&#x1ECF; h&#x1A1;n, &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t &#x1EDF; g&#x1EA7;n ng&#x1B0;&#x1EDD;i d&#xF9;ng nh&#x1EA5;t c&#xF3; th&#x1EC3;. &#x110;i&#x1EC1;u n&#xE0;y gi&#xFA;p &#x111;&#x1EA3;m b&#x1EA3;o tr&#x1EA3;i nghi&#x1EC7;m ng&#x1B0;&#x1EDD;i d&#xF9;ng t&#x1ED1;t h&#x1A1;n, &#x111;&#x1ED3;ng th&#x1EDD;i gi&#x1EA3;m thi&#x1EC3;u chi ph&#xED; v&#x1EAD;n h&#xE0;nh.</p><p>Sharding by design l&#xE0; m&#x1ED9;t gi&#x1EA3;i ph&#xE1;p hi&#x1EC7;u qu&#x1EA3; &#x111;&#x1EC3; gi&#x1EA3;i quy&#x1EBF;t c&#xE1;c challenges trong vi&#x1EC7;c ph&#x1EE5;c v&#x1EE5; kh&#xE1;ch h&#xE0;ng qu&#x1ED1;c t&#x1EBF;. Ch&#xFA;ng t&#xF4;i tin r&#x1EB1;ng, v&#x1EDB;i h&#x1EC7; th&#x1ED1;ng Shard by design, ch&#xFA;ng t&#xF4;i c&#xF3; th&#x1EC3; mang &#x111;&#x1EBF;n tr&#x1EA3;i nghi&#x1EC7;m t&#x1ED1;t nh&#x1EA5;t cho ng&#x1B0;&#x1EDD;i d&#xF9;ng &#x1EDF; m&#x1ECD;i n&#x1A1;i tr&#xEA;n th&#x1EBF; gi&#x1EDB;i.</p>]]></content:encoded></item></channel></rss>