سؤال

أقوم بتطوير تطبيق يقوم بتقديم طلبات إلى Webservice MusicBrainz. قرأت في دليل MusicBrainz لعدم إجراء أكثر من طلب واحد في الثانية الواحدة إلى WebService أو سيتم حظر IP العميل.

ما هي الهندسة المعمارية التي تقترحها من أجل جعل هذا التقييد شفافا لعميل الخدمة.

  • أرغب في استدعاء طريقة (GetalBuns على سبيل المثال)، وينبغي أن يجعل الطلب فقط 1SEC بعد الطلب الأخير.
  • أريد أيضا استدعاء 10 طلب مرة واحدة، ويجب أن تتعامل الخدمة مع وضع قائمة الانتظار، وإرجاع النتائج عند avaiable (غير حظر).

شكرًا!

هل كانت مفيدة؟

المحلول

بسبب التأخير المطلوب بين الدعوات، أود أن أقترح java.util.Timer أو java.util.concurrent.ScheduledThreadPoolExecutor. Timer هو بسيط جدا، وكافية تماما ل هذه حالة الاستخدام. ولكن إذا تم تحديد متطلبات الجدولة الإضافية في وقت لاحق، واحدة Executor يمكن التعامل مع كل منهم. في كلتا الحالتين، استخدم طريقة التأخير الثابت، وليس طريقة معدل ثابت.

المهمة المتكررة استطلاعات الرأي قائمة انتظار متزامنة لكائن الطلب. إذا كان هناك طلب معلق، فإن المهمة تنفذها، وإرجاع النتيجة عبر رد الاتصال. الاستعلام عن الخدمة وإعداء الاتصال لاستدعاء أعضاء في كائن الطلب.

يحتفظ التطبيق مرجعا في قائمة الانتظار المشتركة. للحصول على طلب طلب، ما عليك سوى إضافته إلى قائمة الانتظار.


فقط للتوضيح، إذا كانت قائمة الانتظار فارغة عند تنفيذ المهمة المجدولة، فلن يتم تقديم طلب. سيكون النهج البسيط فقط لإنهاء المهمة، وستحصل الجدولة بإحتساء المهمة واحدة في وقت لاحق للتحقق مرة أخرى.

ومع ذلك، هذا يعني أنه يمكن أن يستغرق ما يصل إلى ثانية واحدة لبدء مهمة، حتى لو لم تتم معالجة طلبات مؤخرا. إذا كان هذا الكمون غير الضروري لا يطاق، فربما يكون كتابة الخيط الخاص بك من الأفضل استخدامه Timer أو ScheduledThreadPoolExecutor. وبعد في حلقة التوقيت الخاصة بك، لديك المزيد من التحكم في الجدولة إذا اخترت حظر حظر قائمة انتظار فارغة حتى يتوفر طلب. الموقود المدمج غير مضمون لانتظار ثانية كاملة بعد التنفيذ السابق تم الانتهاء من; ؛ أنها عادة جدولة نسبة إلى البداية وقت المهمة.

إذا كانت هذه الحالة الثانية هي ما لديك في الاعتبار، run() سوف تحتوي الطريقة على حلقة. كل تكرار يبدأ حظر في قائمة الانتظار حتى يتم استلام الطلب، ثم تسجيل الوقت. بعد معالجة الطلب، يتم فحص الوقت مرة أخرى. إذا كان الاختلاف الزمني أقل من ثانية واحدة، نايم للباقي. يفترض هذا الإعداد أن التأخير الثاني مطلوب بين بدء طلب واحد والآخر. إذا كان التأخير مطلوبا بين نهاية طلب واحد، فإنه لا تحتاج إلى التحقق من الوقت؛ مجرد النوم لمدة ثانية واحدة.

شيء آخر يجب ملاحظته هو أن الخدمة قد تكون قادرة على قبول استفسارات متعددة في طلب واحد، مما يقلل من النفقات العامة. إذا كان الأمر كذلك، استفد من ذلك عن طريق حظر take() للعنصر الأول، ثم استخدام poll(), ربما مع وقت حظر قصير جدا (5 مللي أم لا)، لمعرفة ما إذا كان التطبيق يبذل المزيد من الطلبات. إذا كان الأمر كذلك، فيمكن تجميع هذه في طلب واحد إلى الخدمة. لو queue هو BlockingQueue<? extends Request>, قد تبدو مثل هذا:

    Collection<Request> bundle = new ArrayList<Request>();
    bundle.add(queue.take());
    while (bundle.size() < BUNDLE_MAX) {
      Request req = queue.poll(EXTRA, TimeUnit.MILLISECONDS);
      if (req == null)
        break;
      bundle.add(req);
    }
    /* Now make one service request with contents of "bundle". */

نصائح أخرى

تحتاج إلى تحديد "خدمة وكيل" محلية والتي سيتصل عملائك المحليين.

سيتلقى الوكيل المحلي طلبات وتمريرها إلى الخدمة الحقيقية. ولكن فقط بمعدل رسالة واحدة في الثانية الواحدة.

كيف تفعل هذا يعتمد كثيرا على tecnoligy المتاحة لك.

ستكون أبسط خدمة Java Mutithreaded Mutithreaded MondimeTimeTimeTime الزمنية الثابت والمزامنة. "متغير الطابع الزمني. (على الرغم من أنك ستحتاج إلى بعض البرمجية البهلوانية للحفاظ على طلباتك بالتسلسل).

يمكن أن تعاني خدمة أكثر تطورا مؤشرات ترابط العامل التي تتلقى الطلبات ووضعها في قائمة انتظار مع مؤشر ترابط واحد يلتقط الطلبات ويمرها إلى الخدمة الحقيقية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top