PDA

View Full Version : بهترین روش برای تفسیر رشته های حجیم JSON چیست؟و نحوه کم کردن بار سرور هنگام تفسیر



alirayaneh
سه شنبه 03 شهریور 1394, 03:43 صبح
با سلام و وقت بخیر خدمت تمامی پیشکسوت های برنامه نویسی و توسعه دهنده های وب و موبایل :چشمک:

دوستان برای تفسیر رشته های حجیم json و کم کردن فشار به سرور چه راهی رو پیشنهاد میدن آیا کلاس خاصی برای این کار وجود داره ؟
برای یک شرکت خارجی که در ارتباط با داده و آمار بورس هست پروژه رو مینویسم . که نرم افزار یک سری دیتا ها رو به صورت وب سرویس json دریافت میکنه . که یک سری اطلاعات مربوط به هر بورس هست که حجم رشته دیتاهای برگشتی برای هر بورس در روز ممکن حدود 700 KB تا 1.2 مگ باشه امکان دریافت تک به تک برای هر بورس وجود داره امکان دریافت یک جا برای حدود 40 تا بورس هم وجود داره که حجم دیتا های برگشتی برای کل بورس ها ممکن در یک روز به 30 الی 50 مگ هم برسه

از طرفی قرار هست این شرکت هم زمان همه دیتا ها رو باز به صورت وب سرویس به کلی شرکت دیگه و یک جا ارسال کنه ..

خوب الان مشکی که باهاش سروکار داریم به علت اتصال تعداد زیاد کلاینت و نیاز به پردازش دیتا ها فشر زیادی به سرور وارد میشه . و حجم زیادی از مموری اشغال میشه .
به علت وجود تاریخ انقضا برای دیتاها دریافتی امکان تقسیم بندی وظایف سرور به ساعات مختلف روز هم وجود نداره .
حال پیشنهاد شما برای کم کردن بار سرور در هنگام پردازش دیتا های دریافتی چی هست آیا برای دریافت یک جا و یکباره 50 مگ دیتا و دیکد کردن و تبدیل اون به Array کلاس و یا ماژولی برای php میشناسید . که میزان فضای اشغال شده از رم و سی پی یو رو در هنگام اجرا کم کنه ؟ (به علت وجود لایسنس و ارزش دیتا های مورد نظر امکان پردازش دیتا در سمت کلاینت منتفی است )

ضمنا از فریم ورک لاراول laravel استفاده میکنم .

H:Shojaei
سه شنبه 03 شهریور 1394, 09:10 صبح
json تا وقتی دیکد نشده یه رشتس عملا وشما میتونید دنبال کلاس یا تابعی واسه فشرده سازی رشته باشید به نحوی که به شکل اولش قابل برگشت هم باشه و با json هم به مشکلی نخوره...
php واسه فشرده سازی رشته تابع داره ولی چون من نه استفاده کردم و نه دیدم کسی استفاده کنه حجمی که کم میکنه نمیدونم چقدره...

us1234
سه شنبه 03 شهریور 1394, 10:05 صبح
با تابع gzcompress (http://php.net/manual/en/function.gzcompress.php) می توانید یک رشته را فشرده کنید .

ولی فکر میکنم این کار باعث استفاده بیشتر از رم و سی پی یو باشد .
باید در یک مرحله رشته را دریافت کنید ، در یک مرحله uncompress کنید و سپس json_decode که عملا یک مرحله به پروسه افزوده میشود .

ولی در انتقال ( شاید ) حجم داده های در حال انتقال کم شود و در استفاده از پهنای باند صرفه جویی شود ...

alirayaneh
سه شنبه 03 شهریور 1394, 15:22 عصر
ضمن تشکر از شما سروران . خوب ببینید مشکل ما پهنای باند نیست چون شرکت کارفرما از لحاظ تامین منابع پهنای باند مشکلی نداره .
مشکل اصلی میزان مصرف منابع سی پی یو و رم هست که با پردازش هم چین رشته حجیم بوجود میاد . و هر قدر هم که روی ارتقاع سرور هزینه بشه. با افزایش تعداد سرویس گیرندها یا کلاینت های ما . منابع سی پی یو و رم پاسخ گو نخواهد بود .

alirayaneh
سه شنبه 03 شهریور 1394, 15:34 عصر
گزینه ی دیگری که ما داریم استفاده از سرویس های پردازش ابری هست
گوگل یک سرویس داره . برای پردازش رشته های json اما با توجه به تعداد بالای یک میون ریکورد برای این پلان بالای یک میلون رکورد در روز روزانه 36 دلار میگیره که چیزی حدود 400 دلار در ماه هست . و 4800 دلار در سال هست .

djtrex
سه شنبه 03 شهریور 1394, 21:48 عصر
عموما برای کار با فایل های بزرگ در زبان های مختلف از stream (http://php.net/manual/en/book.stream.php) ها استفاده می کنند. برای parse کردن json به صورت stream هم کتاب خانه ها و اکستنشن هایی برای php ساخته شده:

https://github.com/salsify/jsonstreamingparser
https://github.com/kuma-giyomu/JSONParser
https://github.com/rayward/json-stream

https://github.com/shevron/ext-jsonreader
https://github.com/sfalvo/php-yajl/

---------

djtrex
سه شنبه 03 شهریور 1394, 21:59 عصر
البته اگه مشکلتون پردازش چندباره این json هست و اگه به صورت دوره ای (مثلا ساعتی) اتفاق می افته کافیه اونو پردازش کنید و اونو برای یک ساعت در جایی مثل redis / memcached / دیتابیس یا حتی فایل کش کنید و به کلاینت ها سرویس بدید.


یا اگه مشکل خوندن حجم زیادی از دیتا روی رم و سپس خروجی دادن به کاربر هست (دانلود فایل از طریق سرور) می تونید از stream ها استفاده کنید هر دفعه قسمتی از فایل خونده میشه و به خروجی داده میشه (pipe) :

http://php.net/manual/en/function.stream-context-create.php
http://php.net/manual/en/function.file-get-contents.php (مثال شماره ۴)

alirayaneh
پنج شنبه 05 شهریور 1394, 01:27 صبح
ضمن تشکر از شما دوست عزیز بله اتفاقا به مشکل من اشاره کردید



یا اگه مشکل خوندن حجم زیادی از دیتا روی رم و سپس خروجی دادن به کاربر هست (دانلود فایل از طریق سرور) می تونید از stream ها استفاده کنید هر دفعه قسمتی از فایل خونده میشه و به خروجی داده میشه (pipe) :

http://php.net/manual/en/function.st...ext-create.php (http://php.net/manual/en/function.stream-context-create.php)
http://php.net/manual/en/function.file-get-contents.php (مثال شماره ۴)

اتفاقا مثال شماره چهار رو اویل استفاده میکردم . اما استریم کردن کشیدن دیتا توسط تابعه file_get_content() باعث افزایش میزان بروز خطا در پردازش میدشد و وقتی برسی کردم دیدم . و قتی در یک حلقه قرار میگرفت برخی مواقه دیتا ها رو کامل لود نمیکرد و یک رشته ناقص و بی سرو ته داشتیم . که اونوقت نمیشد دیکد کرد. اما از وقتی توابعی استاندارد curl استفاده میکنیم . بروز چنین مواردی خیلی کمتر اتفاق میفته .

djtrex
جمعه 06 شهریور 1394, 12:57 عصر
ضمن تشکر از شما دوست عزیز بله اتفاقا به مشکل من اشاره کردید



اتفاقا مثال شماره چهار رو اویل استفاده میکردم . اما استریم کردن کشیدن دیتا توسط تابعه file_get_content() باعث افزایش میزان بروز خطا در پردازش میدشد و وقتی برسی کردم دیدم . و قتی در یک حلقه قرار میگرفت برخی مواقه دیتا ها رو کامل لود نمیکرد و یک رشته ناقص و بی سرو ته داشتیم . که اونوقت نمیشد دیکد کرد. اما از وقتی توابعی استاندارد curl استفاده میکنیم . بروز چنین مواردی خیلی کمتر اتفاق میفته .

من منظورم برعکس بود :دی یعنی فایل روی سرور هست ولی حجیمه و اینو میخواین از طریق php اونو serve کنید و کلاینت بتونه اونو دانلود کنه.

برای اونکار curl خوبه ولی من guzzle رو پیشنهاد میکنم:

کد curl:



$fp = fopen ('/path/to/file.json', 'w');

$ch = curl_init('http://example.com/file.json');


curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);


curl_close($ch);


fclose($fp);



کد guzzle نسخه ۶:

اگه میخواین توی یه فایل ذخیره کنید:



$client = new GuzzleHttp\Client();


$resource = fopen('/path/to/file.json', 'w');
$client->get('http://example.com/file.json', ['sink' => $resource]);


اگه میخواید از استریم های psr-7 (http://www.php-fig.org/psr/psr-7/) استفاده کنید: (guzzle استریم decorator های مختلفی رو به صورت پیشفرض داره مثل CachingStream, BufferStream و ... لیستشون:
http://guzzle.readthedocs.org/en/latest/psr7.html#streams )



$client = new GuzzleHttp\Client();


$resource = fopen('/path/to/file.json', 'w');
$stream = GuzzleHttp\Psr7\stream_for($resource);


$client->get('http://example.com/file.json', ['sink' => $stream]);



اگه می خواید به محض دانلود اونو به کاربر ارائه بدید (بدون اینکه اول کل فایل دانلود بشه و رم اشغال بشه بعد همون به کاربر داده بشه):



$client = new GuzzleHttp\Client();


$response = $client->get('http://example.com/file.json', ['stream' => true]);


$body = $response->getBody();


while (!$body->eof()) {
echo $body->read(1024);
}



مستندات کتاب خانه guzzle نسخه ۶ (php 5.5 به بالا):
http://guzzle.readthedocs.org/en/latest/index.html

نسخه ۵.۳ (php 5.4 به بالا):
http://guzzle.readthedocs.org/en/5.3/