WebSocket في Java: تقنيات متقدمة لتطبيقات الوقت الفعلي
\n\nWebSocket هو بروتوكول اتصال ثنائي الاتجاه بالكامل يسمح بإنشاء اتصال دائم بين العميل والخادم. على عكس HTTP، حيث كل طلب ينشئ اتصالاً جديداً، يوفر WebSocket تبادلاً مستمراً للبيانات في الوقت الفعلي. في Java، يتم تنفيذ هذا البروتوكول عبر JSR 356 (Java API for WebSocket) وأطر عمل قوية مثل Spring WebSocket. في هذه المقالة، سنستعرض الجوانب المتقدمة لتطوير تطبيقات الوقت الفعلي في Java: التوسع، التجميع، التكامل مع Spring، ومعالجة السيناريوهات المعقدة.
\n\nهندسة وتوسيع تطبيقات WebSocket في Java
\n\nعند تطوير أنظمة الوقت الفعلي في Java، من المهم فهم أن اتصالات WebSocket هي اتصالات طويلة العمر وتحافظ على الحالة. وهذا يخلق مشاكل عند التوسع: إذا كان التطبيق يعمل على عدة خوادم، كيف نضمن أن الرسالة المرسلة إلى خادم واحد ستصل إلى العميل المتصل بخادم آخر؟
\n\nالحل: استخدام وسيط الرسائل. الحلول الشائعة هي Redis Pub/Sub أو RabbitMQ. تعمل هذه كـ "ناقل" مركزي تتبادل من خلاله جميع الخوادم البيانات. عندما يتلقى خادم رسالة من عميل، ينشرها في الوسيط، وتشترك جميع الخوادم الأخرى في هذه القناة وترسل الرسالة إلى عملائها المتصلين.
\n\nمثال على التكامل مع Redis Pub/Sub في Spring:
\n\n@Component\npublic class RedisMessagePublisher implements MessagePublisher {\n @Autowired\n private StringRedisTemplate stringRedisTemplate;\n\n public void publish(String channel, String message) {\n stringRedisTemplate.convertAndSend(channel, message);\n }\n}\n\n@Service\npublic class WebSocketRedisSubscriber implements MessageListener {\n @Autowired\n private SimpMessagingTemplate messagingTemplate;\n\n @Override\n public void onMessage(Message message, byte[] pattern) {\n String payload = new String(message.getBody());\n // إرسال إلى جميع المشتركين في WebSocket\n messagingTemplate.convertAndSend("/topic/public", payload);\n }\n}\n\nبالإضافة إلى ذلك، للتوسع، من الضروري إدارة الجلسات بشكل صحيح. بدلاً من تخزين الجلسات في ذاكرة خادم واحد (HashMap)، استخدم مخزناً موزعاً مثل Hazelcast أو Redis. سيسمح ذلك لأي خادم في المجموعة بالوصول إلى أي جلسة.
\n\nالعمل المتقدم مع Spring WebSocket و STOMP
\n\nيوفر Spring WebSocket تجريداً عالي المستوى فوق JSR 356. استخدام بروتوكول STOMP (Simple Text Oriented Messaging Protocol) فوق WebSocket يبسط توجيه الرسائل وإدارة الاشتراكات.
\n\nالتكوين المتقدم:
\n\n@Configuration\n@EnableWebSocketMessageBroker\npublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer {\n\n @Override\n public void configureMessageBroker(MessageBrokerRegistry config) {\n // وسيط مدمج للسيناريوهات البسيطة\n config.enableSimpleBroker("/topic", "/queue");\n // بادئات للرسائل من العميل إلى الخادم\n config.setApplicationDestinationPrefixes("/app");\n // استخدام وسيط خارجي (مثل RabbitMQ)\n config.enableStompBrokerRelay("/topic", "/queue")\n .setRelayHost("localhost")\n .setRelayPort(61613)\n .setClientLogin("guest")\n .setClientPasscode("guest");\n }\n\n @Override\n public void registerStompEndpoints(StompEndpointRegistry registry) {\n registry.addEndpoint("/ws")\n .setAllowedOrigins("*")\n .withSockJS(); // حل بديل للمتصفحات القديمة\n }\n}\n\nمعالجة السيناريوهات المعقدة باستخدام التعليقات التوضيحية:
\n\n- \n
@MessageMapping— معالجة الرسائل من العميل. \n