ایجاد API داینامیک در جنگو

سلام دوستان
دریک پروژه نیاز هست که کاربر بتونه توسط UI یک API شخصی سازی شده برای خودش تعریف کنه که بقیه بتونن توسط این API تعریف شده یکسری دیتا رو از سرور بگیرن. این API ایجاد شده در فاز اول تنها GET را پشتیبانی خواهد کرد که دیتای موجود در چندین نوع دیتابیس مختلف (mysql , postgres, mariadb,cassandra, mongodb, oracledb) قرار دارن. در فاز اول هم تصمیم بر اینه که فرض میکنیم کاربر خودش query رو متناسب با نوع دیتابیس مینویسه پس فعلا نیازی نیست در بک یک ORM تعریف کنیم که بتونه کویری رو روی همه دیتابیس ها بزنه و فقط لازمه بدونیم کدوم دیتابیس مد نظرش هست و این کویری رو روی اون دیتابیس میزنیم و فیلدهای مد نظرش رو سریالایز میکنیم و در جواب API شخصی سازی شده میفرستیم.
وقتی کاربری میخواید یک API کاستوم شده تعریف کنه ما این اطلاعات رو ازش میگیرم و در دیتابیس ذخیره میکنیم:

url => url of custom api which user want to create
query => the query related to fetch data from database
 database => the details of data base (server,port,db_name,db_type) which user want to server data through it

حالا بحث اینه چطور این APIرو سرو کنیم. برای این کار یک endpoint جنرال در جنگو به شکل زیر تعریف میکنیم که مسیولیتش سرو تمامی API های تعریف شده توسط کاربران هستش:

api/v1/serve_api/<my_custome_api>/

در این حالت میایم از دیتابیس به دنبال APIای میگردیم که برابر با my_custome_api هست و اطلاعات مربوط به این API رو میخونیم. این اطلاعات شامل نوع دیتابیس و کویری هست که کاربر در حین تعریف API مد نظرش به ما داده، پس فقط میایم این کویری رو روی دیتابیس مد نظر میزنیم و سریالایز میکنیم و در جواب برمیگردونیم.
برای اتصال به دیتابیس های مختلف هم درایورهای مربوطه رو نصب میکنیم و … .
دوستان اگر ممکنه نظرشون رو بگن، حتی اگر پیشنهادی برای سایر تکنولوژی ها و یا سایر زبان ها دارید بیان کنید که ممنون میشم.
جهت اطلاع بیشتر : ۱-پشت این سرویس جنگو کنگ نشسته که مسیولیت پروکسی کردن با اون هست و یکسری کارها رو به عهده kong api management گذاشتیم.
۲- دلیل این پروژه این هست که ما کلی دیتا در شرکت داریم که خام هستند و نیاز هست کلی API روی این دیتابیس ها تعریف کنیم که همکاران بخش های دیگه به راحتی برای خودشون API تعریف کنن و بتونن دیتای مد نظرشون رو فچ کنن از همون طریق.
۳- و یه نکته اینه که ما فرض رو بر این گذاشتیم که سروری با کانفیگ 8 هسته سی پی یو، 12 گیگ رم و ubuntu بتونه برای دیتاهای متوسط (مثلا 50 ریکورد در هر ریکویست از دیتابیس فچ بشه و جوینی در کویری نباشه) به حداقل 200 ریکویست در ثانیه جواب بده.

به نظرم زیادی مساله رو پیچیده کردید.
اولا که اینهمه دیتابیس مختلف در کنار هم لازمه؟ اصلا کنار همدیگه جا میشن؟ مگه چقدر RAM دارید؟ Cassandra به تنهایی بیشتر از ۱۲گیگ رم میخواد.
مساله‌ی دوم اینه که پیشنهاد میکنم از GraphQL استفاده کنید. خیلی از مشکلات رو هندل میکنه. مشکلاتی که فکر میکنید ذاتا باید وجود داشته باشه هم هندل شدست!
درضمن خودش یه DSL ساده ارائه میده برای تعریف کوئریها. یعنی این بخش از مشکل هم هندل شدست!
اصلاح میکنم، DSL نیست. یه چیزی شبیه json هست که ریکوئست رو به اون فرمت تعریف میکنیم میدیم به سرور و به همون فرمت، جواب رو بهمون برمیگردونه.

2 Likes

ممنون پویا جان، جا داره تشکر کنم از اینکه شما همیشه نظرات عالی میدید ومن کلی از نظرات شما رو خوندم و استفاده کردم.
مسئله اینجاست که با کارمندانی که میخوان از این api استفاده کنن نیاز دارن از متلب، پایتون، جاوا، گو، و… ریکویست بزنن که با graphql نمیشه. و مورد بعدی اینه که باید دسترسی به فیلدها و سکوریتی هم هندل بشه و هر کسی نتونه هر چی میخواد برداره. کاساندرا هم با روی سیستم لوکال من که 8 گیگ رم داره بدون مشکل در کنار Postgres و mysql سرویسش بالاست (ولی ریکویست روش نیست خب که نمیدونم چقدر نیاز به رم پیدا میکنه زیر ریکویست ولی میشه کانفیگ سرور رو برد بالا). دلیل استفاده از این دیتابیس ها اینه که چند سال دیتا جمع شده و هر سرویسی بنا به نیازش از الاستیک گرقته تا کاساندرا دیتا برای خودش جمع کرده و این پروژه به نحوی داره یه دیتا پابلیشر می‌سازه. نمونه کوچیکترش appex هست که برای اوراکله.
این دیتاپابلیشر میره به عنوان یه سرویس روی یه سرور و بقیه فقط ازش فچ میکنن.
فازهای بعدی هم اینه که ui بهبود پیدا کنه و شما بدون کویری نوشتن بتونید این قابلیت ها رو به سرگیستون بدید که چه دیتایی رو چه شکلی روی api سرو کنه.

1 Like

این کار شدنیه اما از نظر architecture مشکل داره
اینجا باید data warehouse با data lake ساخته بشه که تمام داده از دیتابیس های مختلف یک جا جمع آوری بشه

2 Likes

ممنون، من با این مفاهیم آشنا نبودم. خیلی خوب ایده ای هستش.
نظرتون در مورد بخش ایجاد api چی هست؟ چطور میشه بهبود داد یا چطور بهتره پیاده سازی بشه؟بخش نحوه جمع آوری دیتا در یک جا و اجرای کویری رو که ایده خوبی دادید من حتما در نظر میگیرم.

چرا نمیشه؟ اصلا graphql ساخته شده که کلاینتهای برنامه نویسی مختلف بتونن باهاش کار کنن. (برای زبانهای مختلف هم لایبرری داره. تست نکردم ولی لایبرری پایتون)
مثلا یه سرور درست میکنن که توش یه سری endpoint و یه سری ریکوئست مجاز، تعریف شده. بعد هر کلاینتی توی هر بخشی از سازمان (میتونه انبار‌داری باشه یا نرم‌افزار android دست کاربر نهایی) هر بخشی از دیتا رو که میخواد، ریکوئست میزنه. این کاریه که الآن Walmart داره انجام میده. یه مطلب درموردش خوندم (شایدم یه talk بود. اگه پیدا کردم منتشر میکنم)

یه مثال:
ریکوئست میزنیم:

{
   students{
      id
      firstName
      lastName
      college{
         name
         location
      }
   }
}

و جواب میاد:

{
   "data": {
      "students": [
         {
            "id": "S1001",
            "firstName": "Mohtashim",
            "lastName": "Mohammad",
            "college": {
               "name": "CUSAT",
               "location": "Kerala"
            }
         }
      ]
   }
}

مسلما دیتای college توی یه جدول دیگست. یا حتی میتونه روی یه دیتابیس دیگه باشه و با یه uuid بین این دوتا دیتابیس ارتباط وجود داشته باشه. کسی که ریکوئست میزنه اصلا درگیر این مسائل نمیشه.
ولی اگه قرار باشه مستقیم به دیتابیس وصل بشیم (با فرض ساده بودن قضیه و اینکه همش روی یه دیتابیس باشه) باید یه کوئری پیچیده بنویسیم به زبان مربوط به اون دیتابیس.

اون که اصلا ربطی به دیتابیس نداره. این مربوط به وب‌سروری هست که ریکوئستها رو قراره هندل کنه.
خود graphql یه api کوچیک هست که هدف ساده و کوچیکی داره و کارش فقط هندل کردن ارتباط بین دیتاهایی هست که جاهای مختلف ذخیره شدن. هندل کردن Authentication و Authorization رو به خودمون واگذار کرده.

2 Likes

مرسی از توضیحات کاملتون، چقدر میشه ایده گرفت از این سایت . ممنون واقعا

2 Likes

درسته به نظر من هم از graphql استفاده کنین خیلی چیز ها راحت تر میشه براتون نسبت به رست

1 Like

من خودم graphql استفاده کردم توی پروژه های خودم
هر سوالی توی پیاده سازی بود در خدمتم
در کنار دوستان
البته اگه بدونم :upside_down_face:

1 Like

ممنونم از راهنماییتون. بنده برم یه مطالعه بکنم در مورد graphql و اینکه مسئله تولید api رو چطور میشه باهاش هندل کرد، سوالاتم رو حتما در بخش مربوطه مینویسم که سایرین از هم راهنمایی شما به شکل طبقه بندی شده در موردش استفاده کنن. بازم ممنونم

1 Like

یه نکته رو همین اول توضیح بدم.
وقتی با graphql کار میکنیم، «تولید api» معنایی نداره.
یعنی اینطوری نیست که «به آدرس site.com/api/users ریکوئست بزنید برای گرفتن دیتای مربوط به کاربرها و آرگومانهاش به شکل فلان خواهد بود»
بیشتر شبیه اینه که «ما یه endpoint داریم site.com/api و دیتایی که میخواید رو به شکل سینتکس graphql مینویسید و میفرستید بهش، جواب رو با همون فرمت دریافت میکنید»

اگه به مثالی که بالاتر زدم دقت کنید مشخصه که ما میگیم «اطلاعات دانش‌آموزها رو میخوام. به شکل id و firstname و lastname و college که این collage باید داخلش name و location باشه»
و جوابی که از سرور دریافت میکنیم دقیقا با همین فرمت از طرف سرور ساخته میشه و بهمون فرستاده میشه.

کاری که برنامه نویس باید سمت سرور انجام بده هم اینه که مشخص کنه یه چیزی به نام student وجود داره که توی فلان جدول از فلان دیتابیسه. یه چیزی به نام college وجود داره که توی فلان جاست و با فلان id وصله به student.
بقیش رو سرور هندل میکنه.

اینکه داخل student چه بخشهایی داشته باشیم رو کاربری که ریکوئست میزنه بیان میکنه! (مثلا وقتی کاربر اطلاعات college رو نخواد، توی ریکوئستی که میزنه نمینویستش. یا اگه مثلا شماره تلفن هم بخواد، اضافه میکنه به ریکوئستش. لازم نیست به یه endpoint دیگه ریکوئست بزنه) پس نیازی نیست برای کارهای مختلف، چندتا endpoint داشته باشیم و چندتا روش مختلف ریکوئست زدن دیتا رو توی داکیومنتهامون بنویسیم و به تیممون بدیم.
برای همین، زحمتش کمتر از RestFul هست. لازم نیست ۱۰۰تا endpoint درست کنیم برای ۱۰۰تا کار و ۱۰۰مدل ریکوئست.

این باعث میشه اضافه کردن قابلیت هم کار راحتی باشه. مثلا تیم برنامه نویسی اندروید میخواد که توی فلان ریکوئستش یه چیز جدید اضافه بشه. بهمون میگه ما اینو توی graphql اضافه میکنیم. تیم اندروید ازش استفاده میکنه و تیم دسکتاپ، اصلا نمیفهمه که اون چیز اضافه شده! الکی هم لازم نیست دیتای اضافه دریافت کنه یا مثلا api doc تغییر کنه مجبور بشن چیزی رو تغییر بدن توی کدهاشون.

البته من توی هیچ پروژه‌ای از graphql استفاده نکردم.

3 Likes