چگونه با استفاده از حافظه پنهان در لبه با HarperDB سرعت برنامه های خود را افزایش دهید

کش کردن یک تکنیک رایج برای افزایش سرعت وب سایت ها و برنامه ها است. “Caching” صرفاً به معنای ذخیره چیزی (مثلاً داده یا یک صفحه وب) است تا در آینده به سرعت به آن دسترسی داشته باشید.
به عنوان مثال، وبسایتهای وردپرسی بهشدت از حافظه پنهان استفاده میکنند تا میزان محاسبات سرور را کاهش دهند. این هزینه ها را کاهش می دهد و به صفحات وب و پست های وبلاگ اجازه می دهد تا به سرعت ارائه شوند.
اگر یک پست وبلاگ ذخیره نمی شد، هر بار که صفحه ای درخواست می شود، داده های پست (عنوان، گزیده، تصویر ویژگی و محتوا) باید از پایگاه داده واکشی شده و به html ارائه شود. اما اگر صفحه ذخیره شود (یعنی html حاصل ذخیره شود)، آنگاه صفحه فقط روی سرور قرار دارد و آماده کار است، و میتواند بلافاصله بدون هیچ تماس پایگاه داده ارائه شود – سرعت سایت را افزایش میدهد.
در این مقاله قصد داریم به یک تکنیک مدرن به نام “Caching at the edge” بپردازیم. سپس یک پروژه ذخیره سازی ساده با HarperDB ایجاد می کنیم تا نتیجه یک فراخوانی API را ذخیره کنیم. سپس سرعت یک مسیر api ذخیره نشده را با یک مسیر api حافظه پنهان مقایسه می کنیم.
خواهید دید که کش کردن نتیجه یک درخواست api سرعت درخواستهای بعدی را افزایش میدهد و همچنین احتمال محدود شدن نرخ برنامه ما را کاهش میدهد.
HarperDB چیست و چرا گزینه خوبی برای کش است؟
HarperDB یک برنامه کاربردی و پلت فرم پایگاه داده توزیع شده است که به شما امکان می دهد تاخیر را کاهش دهید و عملکرد هر مجموعه داده و هر برنامه ای را بهبود بخشید.
“Distributed” به این معنی است که برنامه و پایگاه داده در سراسر جهان پخش شده است. به طور سنتی، یک برنامه وب و پایگاه داده روی یک سرور قرار میگیرند، اما اگر کاربر در فاصله زیادی از سرور قرار داشته باشد، این امر باعث تأخیر زیادی میشود (یک کلمه جالب برای تاخیر) – به عنوان مثال، اگر برنامه در نیویورک باشد، اما کاربر در دهلی است.
اگر برنامه توزیع شده باشد، برنامه بر روی چندین سرور در سراسر جهان قرار دارد، به عنوان مثال کاربر در دهلی میتواند به جای نیویورک، برنامه را از رایانهای در بنگلادش دریافت کند.
محاسبات اج چیست؟
به طور سنتی، هنگامی که یک برنامه وب را نصب می کنید، رایانه ای را اجاره می دهید که در یک مرکز داده فیزیکی در سراسر جهان زندگی می کند – مانند “us-east-2” یا “tt-west-4”. تمام درخواست ها از سراسر جهان به همان سرور می رود. اما مشکل این است که کاربران شما در سراسر جهان پراکنده هستند. سرعت نور سریع است، اما فوری نیست، بنابراین نزدیکتر بودن فیزیکی به سرور، پاسخ سریعتری از سرور به شما میدهد.
توسعه دهندگان وب برای مدت طولانی با استفاده از CDN ها (شبکه های تحویل محتوا) برای توزیع، کپی کردن یا ذخیره فایل های استاتیک – مانند HTML، CSS یا جاوا اسکریپت بر روی سرورهای سراسر جهان، این مشکل را کاهش داده اند. این برای فایلهای استاتیک عالی عمل میکند، اما برای سرور پویا که نیاز به اجرای کدهای سمت سرور در هر درخواست دارد، کار نمیکند.
تعریف ویکی پدیا از محاسبات لبه:
محاسبات لبه یک الگوی محاسباتی توزیع شده است که محاسبات و ذخیره سازی داده ها را به منابع داده نزدیک می کند. انتظار می رود این باعث بهبود زمان پاسخ و صرفه جویی در پهنای باند شود.”
بنابراین، محاسبات لبه مانند یک CDN برای یک سرور تمام عیار است.
Vercel (شرکتی که به ارائه میزبانی عالی Next.js معروف است) توابع لبه ای را ارائه می دهد که مسیرهای api Next.js شما را در سراسر جهان توزیع می کند و آنها را به کاربر نزدیک تر می کند – هر کجا که باشد.
این روی کاغذ عالی به نظر می رسد، اما چه می شود اگر پایگاه داده در یک مکان واحد قرار داشته باشد – مثلا نیویورک. اگر یک کاربر در دهلی درخواستی برای یک مسیر api توزیع شده واقع در بنگلادش ارائه دهد، اما سپس آن مسیر api به مقداری داده از پایگاه داده واقع در نیویورک نیاز دارد، آنگاه سفر رفت و برگشت به این صورت می شود:
دهلی -> بنگلادش -> نیویورک -> بنگلادش -> نیویورک.
این درخواست حتی بیشتر از زمانی طول می کشد که برنامه و داده ها توزیع نشده باشند و فقط در نیویورک نشسته باشند، با یک رفت و برگشت کوتاه تر:
دهلی -> نیویورک -> دهلی.
بنابراین، اگر ما در حال توزیع برنامه خود هستیم، پس (بسته به مورد استفاده خاص شما) معمولاً توزیع داده ها همراه با برنامه ایده خوبی است.
اما ایجاد و نگهداری سیستم های توزیع شده می تواند بسیار پیچیده باشد. این جایی است که HarperDB وارد می شود. HarperDB با توزیع مسیرهای api و داده های شما در سراسر جهان، قرار دادن برنامه شما (مثلاً مسیرهای api) درست در کنار پایگاه داده و برنامه و داده های شما به کاربر نهایی نزدیک تر، تأخیر هر مجموعه داده را کاهش می دهد.
این امر HarperDB را به یک نامزد عالی برای کش لبه تبدیل میکند: ما میتوانیم دادهها را کش (ذخیره در پایگاه داده HarperDB خود) کنیم و این کش را در سراسر جهان توزیع کنیم.
با HarperDB، سرور API در خود پایگاه داده ادغام می شود (ویژگی که به عنوان “توابع سفارشی” شناخته می شود)، به این معنی که یک جهش کمتر از api به پایگاه داده وجود دارد که باعث کاهش بیشتر تأخیر می شود و به کاربران ما خدمات خوبی و سریع ارائه می دهد.
برای اطلاعات بیشتر در مورد حافظه پنهان لبه، Edge Caching Explained & چرا باید از آن استفاده کنید را بررسی کنید.
بیایید اکنون یک پروژه ساده برای کش کردن نتیجه یک درخواست api بسازیم…
پروژه ذخیره سازی HarperDB
چیزی که قراره بسازیم
ما قصد داریم تفاوت سرعت یک مسیر api ذخیره نشده را با مسیری که نتیجه یک فراخوانی api را ذخیره می کند، مقایسه کنیم.
در مسیر ذخیره نشده، ما به سادگی یک پست با شناسه را از JSONPlaceholder API دریافت می کنیم. https://jsonplaceholder.typicode.com/posts/${id}
، در هر درخواست، و آن را به کاربر برگردانید.
در مسیر ذخیره شده، نتیجه هر درخواست به را کش می کنیم https://jsonplaceholder.typicode.com/posts/${id}
.
منطق مسیر ذخیره شده ساده است:
- شناسه پست را از url دریافت کنید و پست را از پایگاه داده HarperDB واکشی کنید.
- اگر پستی پیدا شد (به عنوان مثال در حافظه پنهان) آن را برگردانید. (ما تمام شدیم.)
- اگر هیچ پستی در پایگاه داده با آن شناسه یافت نشد، پست را از API واکشی کنید.
- پست را در پایگاه داده ذخیره کنید (کش)
- پست را برگردانید.
- بیا شروع کنیم.
نصب HarperDB به صورت محلی
HarperDB را به صورت محلی برای مک، ویندوز یا لینوکس نصب کنید.
من در مک هستم، بنابراین برای نصب HarperDB یک ترمینال را باز کردم و وارد کردم:
$ npm install -g harperdb
این نمونه HarperDB نصب شده در مک من در مقصد قرار دارد: /Users/danadams/hdb Server
با:
- پورت Listening: 9925
- نام کاربری برای HDB_ADMIN: HDB_ADMIN
- رمز عبور: whatever_you_set_this_to_during_installation
اکنون می توانیم HarperDB را با دستور زیر راه اندازی کنیم:$ harperdb
اکنون می توانیم از HarperDB به صورت محلی استفاده کنیم!
راه اندازی استودیو HarperDB
ابتدا یک حساب کاربری با HarperDB ایجاد کنید.
سپس باید نمونه HarperDB نصب شده محلی خود را با ثبت یک نمونه نصب شده توسط کاربر متصل کنیم:
“ثبت نمونه نصب شده توسط کاربر” را انتخاب کنید:
سپس نمونه محلی HarperDB را که در مرحله قبل نصب کردید وصل کنید:
ایجاد طرحواره ما
بیایید طرحی به نام “caching_project” ایجاد کنیم. یک طرحواره فقط یک روش فانتزی برای گفتن “گروه جداول” در HarperDB است.
سپس، در caching_project
طرحواره، جدولی به نام ایجاد کنید single_post
با hash_attribute of id
. یک hash_attribute به نوعی مانند یک کلید اصلی منحصر به فرد برای یک ردیف در یک جدول است.
ایجاد یک پروژه تابع سفارشی
در HarperDB، توابع سفارشی مسیرهای سفارشی هستند که میتوانیم آنها را برای انجام هر کاری که میخواهیم تعریف کنیم – معمولاً برای تعامل با پایگاه داده HarperDB خود به نحوی. اساساً، توابع سفارشی به ما این امکان را میدهند که api خود را درست در کنار جایی که دادههایمان ذخیره میشود بسازیم و تأخیر را کاهش دهیم.
توابع سفارشی توسط Fastify (یک چارچوب سبک وزن Node.js که ادعا میکند سریعتر از Express.js است) ارائه میشوند، بنابراین بسیار انعطافپذیر هستند.
برای چرخاندن یک پروژه توابع سفارشی جدید، به تب توابع بروید، روی نماد ‘+’ در کنار ‘projects’ کلیک کنید و پروژه ای به نام ایجاد کنید. caching-project
:
در مرحله بعد، یک فایل در پوشه ‘routes’ به نام ‘post’ ایجاد کنید. اینجا جایی است که ما راهنمایهای مسیر خود را برای واکشی پستهای وبلاگ تکی مینویسیم.
HarperDB چند نمونه از مسیرها را ارائه می دهد، اما بیایید همه چیز را پاک کنیم و یک مسیر ساده برای آزمایش درستی ایجاد کنیم:
'use strict';
module.exports = async (server, { hdbCore, logger }) => {
// Test route
server.route({
url: '/test',
method: 'GET',
handler: () => {
return 'It works!' // This should be printed out in browser
}
})
};
نشانی اینترنتی توابع سفارشی خود را در گوشه سمت چپ پایین برگه «عملکردهای سفارشی» پیدا کنید:
بازدید از caching-project/test
مسیر:
کمال!
توجه داشته باشید که ما همچنین می توانیم با باز کردن پروژه به صورت محلی، توابع سفارشی خود را در ویرایشگر متن مورد علاقه شما بنویسیم. در مک، توابع سفارشی در قرار دارند /Users/your_username/hdb/custom_functions
، بنابراین برای باز کردن با VS Code در مک:
- یک ترمینال باز کنید
$ cd hdb
$ cd custom_functions
$ code .
اکنون، میتوانید کد خود را در ویرایشگر متن خود ویرایش کنید، سپس به تب توابع استودیو HarperDB بروید، روی بارگذاری مجدد کلیک کنید تا تغییرات محلی خود را ببینید، سپس روی دکمه سبز ذخیره برای بهروزرسانی کلیک کنید.
اما برای این پروژه ساده، من فقط آن را بال میدهم و کد را مستقیماً در استودیوی HarperDB مینویسم.
ایجاد یک مسیر ذخیره نشده
بیایید مسیری ایجاد کنیم که یک پست را با شناسه آن از API JSONPlaceholder دریافت کند، سپس آن را به کاربر برگرداند:
// Fetch a post by id from JSONPlaceholder api
server.route({
url: '/post/:id',
method: 'GET',
handler: () => {
const postId = request.params.id;
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
const post = await response.json();
return post;
}
})
حالا بیایید Postman (یک نرم افزار محبوب برای آزمایش سریع مسیرهای api) را برای رسیدن به این نقطه پایانی باز کنیم و ببینیم چقدر طول می کشد تا داده ها را دریافت کنیم:
پس از چند بار کلیک کردن روی “ارسال”، درخواست بین 35 تا 200 میلیثانیه طول میکشد و بیشتر درخواستها حدود 45 میلیثانیه طول میکشد. بیایید ببینیم آیا میتوانیم آن را با ذخیره کردن نتایج تماسهای API بهبود بخشیم…
ایجاد یک مسیر ذخیره شده در حافظه پنهان
بیایید منطق مسیر ذخیره شده را به خود یادآوری کنیم:
شناسه پست را از url دریافت کنید و پست را از پایگاه داده HarperDB واکشی کنید.
- اگر پستی پیدا شد، آن را برگردانید. (ما تمام شدیم.)
- اگر هیچ پستی در پایگاه داده با آن شناسه یافت نشد، پست را از API واکشی کنید.
- پست را در پایگاه داده ذخیره کنید.
- پست را برگردانید.
قرار دادن این منطق در کد:
server.route({
url: "/cached-post/:id",
method: "GET",
preParsing: (request, response, payload, done) => {
request.body = {
...request.body,
operation: "sql",
sql: `SELECT * FROM caching_project.single_post WHERE id = '${request.params.id}'`,
};
done();
},
handler: async (request) => {
const cachedPost = await hdbCore.requestWithoutAuthentication(request);
if (cachedPost.length === 1) {
// Post found in db, so return it.
return cachedPost[0];
}
// Post not cached/found in db, so fetch post from api
const postId = request.params.id;
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
const newPost = await response.json();
// Add the HarperDB operation to insert the post into the db
request.body = {
operation: "insert",
schema: "caching_project",
table: "single_post",
records: [newPost],
};
// Cache (save) the result in db
hdbCore.requestWithoutAuthentication(request);
// Return the post
return newPost;
},
});
بالای preParsing
callback عملیات HaperDB را که می خواهیم انجام دهیم به بدنه درخواست اضافه می کند. این عملیات پست با شناسه را از پایگاه داده دریافت می کند.
سپس استفاده می کنیم hdbCore.requestWithoutAuthentication(request)
برای انجام عملیات پایگاه داده بدون مجوز (این مسیرها باید به صورت عمومی در دسترس باشند، بنابراین نیازی به احراز هویت نیست). اگر پست پیدا شد، آن را برمی گردانیم. در غیر این صورت، آن را از api دریافت می کنیم، آن را در پایگاه داده HarperDB خود ذخیره می کنیم و سپس آن را برمی گردانیم.
اکنون وقتی برای اولین بار به نقطه پایانی خود رسیدیم، باید 118 میلی ثانیه صبر کنیم تا پاسخ را دریافت کنیم:
اما وقتی دوباره به همان مسیر رفتیم (با همان شناسه پست)، فقط 10 میلی ثانیه طول می کشد:
چرا درخواست اول کندتر است؟ از آنجا که وقتی کاربر برای اولین بار یک پست درخواست می کند، آن پست ذخیره نمی شود (در db ما ذخیره می شود)، بنابراین پست باید از api واکشی شود، در db ما ذخیره شود، سپس به کاربر برگردانده شود.
اما درخواستهای بعدی برای همان پست سریعتر خواهد بود، زیرا پست اکنون در پایگاه داده ذخیره میشود و میتوان بلافاصله آن را دریافت و بازگرداند.
بنابراین، با کش کردن با هارپر دیبی، تأخیر درخواست را 4 تا 5 برابر کاهش دادهایم (از ~45 میلیثانیه بدون کش به 10 میلیثانیه کش).
می توانید بررسی کنید که چه داده هایی از استودیو HarperDB ذخیره شده است:
چگونه می توانیم استراتژی ذخیره سازی خود را بهبود بخشیم؟
در حال حاضر، حافظه پنهان ما تاریخ انقضا ندارد، به این معنی که اگر یک پست در JSONPlaceholder API بهروزرسانی شود، ما هرگز بهروزرسانی را نمیبینیم زیرا حافظه پنهان ما دائمی است. برای اجازه دادن بهروزرسانیهای پست، میتوانیم یک ستون تاریخ انقضا را به هر یک از ردیفهای حافظه پنهان اضافه کنیم تا کش پس از چند ساعت منقضی شود. سپس، اگر حافظه نهان منقضی شده است، میتوانیم پست را از JSONPlaceholder دوباره واکشی کنیم و حافظه پنهان را در پایگاه داده بهروزرسانی کنیم، و مطمئن شویم که حافظه پنهان ما هرگز بیش از چند ساعت قدیمی نیست.
خلاصه
HarperDB یک گزینه عالی برای کش کردن داده ها است زیرا برنامه و داده ها را به کاربر نزدیک می کند (همچنین به عنوان کش لبه شناخته می شود)، تاخیر را کاهش می دهد و سرعت برنامه شما را افزایش می دهد.
اگر از این مقاله لذت بردید، یک ساب در یوتیوب یا من را در توییتر دنبال کنید.
با تشکر برای خواندن!