Dave- ը երբեք չի տեսնում Fire Alarm System- ը, բայց նա պարզապես ավարտել է հաճախորդների ծառայության նախագծը, որտեղ «private phone calls increase engagement by 847%!», այնպես էլ, Dave- ը կարծում է: «Fire alarms are just customer service for emergencies!» «Ես միշտ պատասխանում եմ, երբ ցանկացած բուժական ալբոմը բացվում է, ես հավատում եմ, որ դա մեքենայի ալբոմ է, եւ չգիտեմ այն»: Fase 1: Point-to-Point հաղորդագրություն (The Phone Call Fiasco) Երբ սեղմվում է սխալը, համակարգը զանգահարում է Hotel- ի բոլոր սենյակները: «Այս սենյակում՝ 301 սենյակում՝ «Այս սենյակում՝ 847 սենյակում՝ մեկ մեկ» եւ «Այս սենյակում՝ մեկ սենյակում՝ մեկ»։ Ի՞նչ է տեղի ունենում, երբ սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի։ «Այո, սա խմում է տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային տրանսպորտային»: Սեղմեք Մինչեւ սենյակում 512- ը տուն է, ով սխալ է: Սենյակում 623-ը ժամ առաջ ստուգել է, բայց հեռախոսը կանգնած է: Սենյակում 108-ին սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռական սեռ Դա Classic Point-to-Point հաղորդագրություն - մեկ ուղարկիչ, մեկ ստանումը, repeated 847 անգամ. Այն չի ծախսում, այն չի արդյունավետ, եւ այն վախենում է բոլոր ներգրավված. «Ես չգիտեմ, թե ինչպե՞ս կարող եմ անել», - ասում է անգլերենը: «Ես չգիտեմ, թե ինչպե՞ս կարող եմ անել», - ասում է անգլերենը: Արդյունքը 2 - Broadcast Communication (The Nuclear Option) «Ես ունեմ ավելի լավ գաղափար», - ասում է նա. Dave- ը տեղադրում է մի խոշոր Fire Alarm, որը թռչվում է ամբողջ օդանավակայքում: Շնորհակալություն! Բոլորը լսում են այն! Բայց ապա Dave- ը հասկանում է, որ այս համակարգը հարմար է հայտարարությունների համար: Պոլիոնը կանգնած է: Fire Alarm: Սննդակը 10 րոպեում կանգնած է: Fire Alarm: Հեռած երեխան: Fire Alarm: Yoga դասընթացը սկսվում է: Fire Alarm: «Այս շաբաթ՝ 47 անգամ զանգված են սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի սննդի ս Դա մի հաղորդագրություն բոլորի համար, եթե նրանք ուզում են այն կամ ոչ: Դա նման է, որ օգտագործեք ամբողջ քաղաքում անջատության հաղորդագրության համակարգը, որպեսզի հայտարարել եք ձեր տրանսպորտային վաճառքը: Ապրիլ 3 - Dave Discovers Something Revolutionary Dave- ի երեք փորձը: «Ո՞վ է, եթե մենք ունենք տարբեր intercoms տարբեր տարածքներում?» Նա տեղադրում է լայնացուցիչներ ամբողջ հյուրանոցում, բայց մատակարարում է նրանց միասին քոլովակներ: «Pool Area Intercom»: «Pool closing in 10 minutes, towel service ending» (Այս յս յս յս յս յս յս յս յս յս յս) «Այս ժամանակը սկսվում է» - «Այս ժամանակը սկսվում է», «Այս ժամանակը ավարտվում է» Conference Room Intercom- ը: «Համշակման սենյակ B- ը հասանելի է, Wi-Fi- ը փոխվել է» Spa Intercom- ը: «Այսպայման մայթացիոններ հասանելի են, saunas maintenance at 3pm» «Այս սերտիֆիկներ»: «Այս սերտիֆիկները կանգնած են 7 սերտիֆիկների վրա» Տղամարդիկ բնականորեն ստանում են intercoms տեղում, որոնք նրանք իրականում օգտագործում են. Բլան տիրախները լսում են pool updates, ռեստորան տիրախները ստանում են սննդի տեղեկատվություն, kongress participants get meeting room announcements. What Dave Actually Built: Publish-Subscribe (Pub/Sub) Ոչ այն, թե ինչի հետ է դադարում, նա ստեղծել է մի - Մեկը առավել կարեւոր մոդելներ նորաձեւ ծրագրային դիզայնի. publish-subscribe system Այսպիսին է, թե ինչպես աշխատում է: Պահպանողները (հավահանգների աշխատակիցները) հաղորդագրությունները ուղարկել են որոշ բաղադրիչների կամ քանակների համար (հավահանգների նորություններ, ռեստորանների նորություններ եւ այլն): Հեղինակներ (հեղինակներ) ընտրում են, թե ինչ մասին ցանկանում են լսել Փակցիչները չգիտեն, թե ով լսում է, սեղմիչները չգիտեն, թե ով տպագրում է: Նրանք ամբողջականորեն կախված են Այսն է N×M հաղորդագրություն: Շատ գրասենյակներ կարող են ուղարկել բազմաթիվ գրասենյակներին, բայց այն տեղադրված է եւ սեղմվում է: Ոչ ավելի սխալ, ոչ ավելի մոռացված հաղորդագրություններ, ոչ ավելի ցանկացած սենյակը միասին զանգահարելու համար: Ինչո՞ւ այն կարեւոր է ձեր կոդը համար Dave սխալով կառուցել է երեք հիմնական հաղորդագրության մոդելներ: Արդյոք, երբ դուք պետք է տեղեկացնել մի քանի համակարգեր, այն չի ծախսում. Point-to-Point Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդված՝ Հիմնական հոդվածը Broadcast Նկարագրողները ուղարկել են հաղորդագրություններ տեքստների / քանակների համար, սեղմողները ընտրել են, թե ինչ է լսել: Scalable, decoupled, and efficient. Pub/Sub Հիմնական համակարգում, pub/sub- ը լուծում է նույն խնդիրները, որոնք Dave-ի հետ կանգնած են: E-commerce: Արդյունաբերական թարմացումներ գնում են բազմաթիվ ծառայությունների համար (նշմաններ, analytics, հաղորդագրություններ) առանց սարքավորումների ծառայությունը գիտի, թե ով լսում է Chat apps: Մեքստային հաղորդագրություններ, որոնք տվել են Channel- ում, օգտագործողները գրանցում են խոսքեր, որոնք նրանք են Microservices: Services- ը գրում է գործառույթներ (բեռնում է օգտվողը, ավարտվել է आदेशը), որոնք այլ ծառայություններ կարող են պատասխանել ինքներդ: Տեղադրեք ձեր սեփական Pub / Sub System (It's Easier Than You Think) Գլխավոր / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ / Ապրանքներ from collections import defaultdict from typing import Dict, List, Callable class HotelPubSub: def __init__(self): self.channels: Dict[str, List[Callable]] = defaultdict(list) def subscribe(self, channel: str, callback: Callable): """Guest subscribes to hotel updates""" self.channels[channel].append(callback) print(f"Subscribed to {channel}") def publish(self, channel: str, message: str): """Hotel staff publishes updates""" if channel in self.channels: for callback in self.channels[channel]: callback(message) print(f"Published to {channel}: {message}") # Dave's hotel in action hotel = HotelPubSub() # Guests subscribe to what they care about def pool_guest(msg): print(f"🏊 Pool Guest: {msg}") def restaurant_guest(msg): print(f"🍽️ Restaurant Guest: {msg}") hotel.subscribe("pool", pool_guest) hotel.subscribe("restaurant", restaurant_guest) # Hotel publishes updates hotel.publish("pool", "Pool closing in 10 minutes!") hotel.publish("restaurant", "Happy hour starts now!") Արդյոք դա է: A working pub/sub system in 20 lines. Async Queues- ի օգտագործումը Ի՞նչ է անել, եթե Dave- ի հյուրանոցը իրականում պակաս է: Մեր պարզ տարբերակը բլոգում է գրասենյակներին, երբ գրասենյակները պակաս են: import asyncio from asyncio import Queue from collections import defaultdict class AsyncPubSub: def __init__(self): self.channels = defaultdict(list) self.message_queue = Queue() # Start background worker asyncio.create_task(self._worker()) def subscribe(self, channel: str, callback): self.channels[channel].append(callback) async def publish(self, channel: str, message: str): # Non-blocking publish - just queue it await self.message_queue.put((channel, message)) async def _worker(self): # Background worker processes messages while True: channel, message = await self.message_queue.get() if channel in self.channels: # Run all subscribers in parallel tasks = [callback(message) for callback in self.channels[channel]] await asyncio.gather(*tasks, return_exceptions=True) # Dave's async hotel in action async def demo(): hotel = AsyncPubSub() # Fast and slow subscribers async def fast_guest(msg): await asyncio.sleep(0.1) # Quick processing print(f"🏊 Fast: {msg}") async def slow_guest(msg): await asyncio.sleep(2.5) # Simulate slow database write print(f"🍽️ Slow: {msg}") hotel.subscribe("updates", fast_guest) hotel.subscribe("updates", slow_guest) # Publishers don't wait for slow subscribers await hotel.publish("updates", "Pool closing!") await hotel.publish("updates", "Happy hour!") await asyncio.sleep(0.2) # Let everything finish # asyncio.run(demo()) Այժմ գրասենյակները երբեք չի բլոգում - նրանք պարզապես տեւում են հաղորդագրությունները եւ շարունակվում են: Բջջային աշխատողը մատակարարում է բոլոր գրասենյակներին միասին: արագ գրասենյակները ստանում են իրենց հաղորդագրությունները արագ (0.1s), իսկ արագ գրասենյակները տեւում են ձեր ժամանակը (2.5s), բայց ոչինչ չի բլոգում միասին: The Easy Performance Hack- ը: uvloop Dave- ի async համակարգը լավ աշխատում է, բայց ապա նա հասկանում է մի բան գեղեցիկ: մի գծի կոդը փոխելու համար ամեն ինչ կարող է լինել 2-4x արագ: Dave- ը կարծում է, որ դա բացառապես շատ լավ է, բայց որոշում է փորձել այն նույնպես: Գնացեք - Python- ի ստանդարտ գործառույթը, որը գրվել է Cython- ում եւ հիմնված է libuv- ում (հա նույն բան, որը Node.js- ը արագ է): uvloop import uvloop import asyncio from collections import defaultdict import time # The magic line that makes Dave's hotel 2-4x faster asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) class TurboHotelPubSub: def __init__(self, max_queue_size=10000): self.channels = defaultdict(list) self.message_queue = asyncio.Queue(maxsize=max_queue_size) self.running = True self.performance_metrics = { 'messages_per_second': 0, 'avg_latency_ms': 0, 'active_subscribers': 0 } # Start background worker and metrics collector asyncio.create_task(self._worker()) asyncio.create_task(self._metrics_collector()) def subscribe(self, channel: str, callback): self.channels[channel].append(callback) self.performance_metrics['active_subscribers'] = sum(len(subs) for subs in self.channels.values()) print(f"Subscribed to {channel} (Total subscribers: {self.performance_metrics['active_subscribers']})") async def publish(self, channel: str, message: str): timestamp = time.time() message_with_timestamp = (channel, message, timestamp) try: self.message_queue.put_nowait(message_with_timestamp) except asyncio.QueueFull: # Backpressure - with uvloop, this is much faster await self.message_queue.put(message_with_timestamp) async def _worker(self): """Background worker - uvloop makes this significantly faster""" while self.running: channel, message, publish_time = await self.message_queue.get() # Measure end-to-end latency processing_start = time.time() if channel in self.channels: # uvloop excels at handling many concurrent tasks tasks = [] for callback in self.channels[channel]: if asyncio.iscoroutinefunction(callback): tasks.append(callback(message)) else: # uvloop's thread pool is much more efficient tasks.append(asyncio.get_event_loop().run_in_executor(None, callback, message)) # uvloop's gather is optimized for many concurrent operations await asyncio.gather(*tasks, return_exceptions=True) # Track latency total_latency = (time.time() - publish_time) * 1000 # Convert to ms self.performance_metrics['avg_latency_ms'] = ( self.performance_metrics['avg_latency_ms'] * 0.9 + total_latency * 0.1 ) self.message_queue.task_done() async def _metrics_collector(self): """Track messages per second - uvloop's timer precision helps here""" last_time = time.time() last_count = 0 while self.running: await asyncio.sleep(1) current_time = time.time() # In uvloop, queue.qsize() is more accurate and faster current_count = getattr(self.message_queue, '_finished', 0) if current_time - last_time >= 1: messages_processed = current_count - last_count self.performance_metrics['messages_per_second'] = messages_processed last_time, last_count = current_time, current_count def get_performance_stats(self): return self.performance_metrics.copy() # Dave's hotel with uvloop superpowers async def benchmark_uvloop_vs_standard(): """Demonstrate uvloop performance improvements""" # Simulate I/O-heavy subscribers (database writes, API calls) async def database_subscriber(msg): # Simulate database write await asyncio.sleep(0.001) # 1ms "database" call return f"DB: {msg}" async def api_subscriber(msg): # Simulate API call await asyncio.sleep(0.002) # 2ms "API" call return f"API: {msg}" def analytics_subscriber(msg): # Simulate CPU-heavy sync work time.sleep(0.0005) # 0.5ms CPU work return f"Analytics: {msg}" hotel = TurboHotelPubSub() # Subscribe multiple handlers to same channel for i in range(10): # 10 database subscribers hotel.subscribe("orders", database_subscriber) for i in range(5): # 5 API subscribers hotel.subscribe("orders", api_subscriber) for i in range(20): # 20 analytics subscribers hotel.subscribe("orders", analytics_subscriber) print("Starting benchmark with uvloop...") start_time = time.time() # Publish lots of messages for i in range(1000): await hotel.publish("orders", f"Order #{i}") # Wait for processing to complete await hotel.message_queue.join() end_time = time.time() stats = hotel.get_performance_stats() print(f"Benchmark complete in {end_time - start_time:.2f} seconds") print(f"Performance stats: {stats}") print(f"Total subscriber callbacks: {stats['active_subscribers'] * 1000:,}") return end_time - start_time # Uncomment to run benchmark # asyncio.run(benchmark_uvloop_vs_standard()) What uvloop supercharges: 1. I/O-Heavy Subscribers (2-4x speedup) Database writes, API calls, ֆայլերի գործառույթները uvloop- ի libuv- ի հիմնված վերլուծությունը ավելի արդյունավետ է վերլուծել միասնական I/O գործառույթները Dave- ի հյուրանոցը կարող է վերահսկել Mrs. Henderson- ի Cloud- ի օրինակը եւ Mr. Peterson- ի Instagram- ի գրքերը միասին 2. Many Concurrent Subscribers (1.5-2x speedup) Համակարգչություններ, որոնք միասին տոնել են միասին միասին միասին միասին միասին միասին միասին միասին uvloop- ի optimized գործառույթների պլանավորումը նվազեցնում է overhead- ը Ավելի լավ է Dave- ի սենյակային կենտրոնի համար, որը 500+ սենյակային հաղորդագրության գրասենյակների հետ 3. Thread Pool Operations (30-50% improvement) Sync callbacks, որոնք փոխվում են thread pool- ում uvloop- ի thread pool- ի կառավարումը ավելի արդյունավետ է Ավելի լավ է Dave- ի թագավոր համակարգերի համար, որոնք չեն կարող լինել async 4. Timer and Queue Precision Բարձր ճշգրիտ ժամանակագրություն մետրիկների եւ ծախսերի սահմանափակման համար Լավագույն կատարման վերահսկողություն Տեղադրում է Dave- ը, եթե իր համակարգը փնտրում է պահանջը Real-world uvloop impact for Dave's hotel: # Before uvloop: 15,000 notifications/second # After uvloop: 35,000 notifications/second # Same code, 2.3x faster! Լավագույն մասը։ Dave- ը ստուգում է, որ երբեմն լավագույն optimizations- ը այն են, որոնք պահանջում են ամենամեծ աշխատանքը: Zero code changes Dave- ի պատասխանը: «Հեռնել, այն է, ես պարզապես ներբեռնում եմ uvloop- ը եւ ամեն ինչ արագ է: Սա զգում է, որ սխալ է!» «Այսը ոչ ոք չի սխալում, Dave. Դա միայն լավ ինժեներություն է. When uvloop matters most: High Subscriber Count: 100+ գրասենյակներ մեկ Channel- ում I/O-heavy callbacks: Database writes, API calls, ֆայլերի գործառույթներ Մխիթարային աշխատանքային տրանսպորտային: Fast and Slow Subscriptors Հասկածություն-հասկածություն: Երբ ամեն միլեսգետն կասկածվի Երբ uvloop- ը արագում է asyncio-ը, որոշ մշակողները սիրում են Trio- ը միասնական գործառույթների միասնական համակարգերի համար: Trio-ի կառուցված միասնական գործառույթը եւ տեղադրված backpressure- ի վերահսկողությունը կարող է լինել ավելի հավասար: Այն նախագծված է սխալել գեղեցիկորեն, քան վատորեն, երբ դուք ունեք 10,000- ից ավելի միասնական գործառույթներ: Dave- ի Hotel- ի համար asyncio +uvloop- ը հարմար է: Dave- ի հաջորդ գործառույթի համար (դիմնական ժամանակային առեւտրային համակարգը ջրի ներքեւի ապրանքների համար), Trio- ը կարող է խուսափել մի քանի 3am debugging sesions: A note about Trio: Dave- ը փորձում է տեղադրել uvloop- ը եւ սխալ հաղորդագրությունները կախված են: Այստեղ այն բան է, որ uvloop- ը պահանջում է համադրություն, այնպես որ դուք պետք է տեղադրել զարգացման գործիքներ: Ubuntu/Debian- ում: macOS- ի հետ Homebrew- ի հետ: Windows- ում... Այո, Dave- ը որոշում է վերցնել Windows- ում ստանդարտ գործառույթը եւ տեղադրել Linux- ում արտադրանքի մեջ: Երբեմն ճիշտ ընտրությունը այն ճանապարհը է, որտեղ ամենամեծ resistance- ը է: The uvloop installation gotcha: apt-get install build-essential brew install python3-dev Going Nuclear: Memory-Mapped Pub/Sub սարքավորումներ Բարձր կատարման կամ multi-process սերտիֆիկների համար, մենք կարող ենք օգտագործել համատեղելի մանրամասի հետ ամբողջական սերտիֆիկների կառավարման: import mmap import struct import multiprocessing import threading import time from collections import defaultdict from typing import Callable, Dict, List class MemoryMappedPubSub: def __init__(self, buffer_size=1024*1024): # 1MB buffer # Create shared memory buffer self.buffer_size = buffer_size self.shared_file = f'/tmp/pubsub_{multiprocessing.current_process().pid}' # Initialize memory-mapped file with open(self.shared_file, 'wb') as f: f.write(b'\x00' * buffer_size) self.mmap = mmap.mmap(open(self.shared_file, 'r+b').fileno(), 0) # Layout: [head_pos][tail_pos][message_data...] self.head_offset = 0 self.tail_offset = 8 self.data_offset = 16 # Subscriber management self.subscribers: Dict[str, List[Callable]] = defaultdict(list) self.listening = False self.listener_thread = None def subscribe(self, channel: str, callback: Callable): """Subscribe to a channel with a callback function""" self.subscribers[channel].append(callback) print(f"Subscribed to channel: {channel}") # Start listener if not already running if not self.listening: self.start_listening() def start_listening(self): """Start background thread to listen for messages""" if self.listening: return self.listening = True self.listener_thread = threading.Thread(target=self._listen_loop, daemon=True) self.listener_thread.start() print("Started listening for messages...") def stop_listening(self): """Stop the message listener""" self.listening = False if self.listener_thread: self.listener_thread.join() def _listen_loop(self): """Background loop that processes incoming messages""" while self.listening: messages = self.read_messages() for message in messages: self._process_message(message) time.sleep(0.001) # Small delay to prevent excessive CPU usage def _process_message(self, message: str): """Process a single message and notify subscribers""" try: if ':' in message: channel, content = message.split(':', 1) if channel in self.subscribers: for callback in self.subscribers[channel]: try: callback(content) except Exception as e: print(f"Error in callback for channel {channel}: {e}") except Exception as e: print(f"Error processing message: {e}") def publish(self, channel: str, message: str): """Ultra-fast direct memory write""" data = f"{channel}:{message}".encode() # Get current tail position tail = struct.unpack('Q', self.mmap[self.tail_offset:self.tail_offset+8])[0] # Check if we have enough space (simple wraparound) available_space = self.buffer_size - self.data_offset - tail if available_space < len(data) + 4: # Reset to beginning if we're near the end tail = 0 # Write message length + data struct.pack_into('I', self.mmap, self.data_offset + tail, len(data)) self.mmap[self.data_offset + tail + 4:self.data_offset + tail + 4 + len(data)] = data # Update tail pointer new_tail = tail + 4 + len(data) struct.pack_into('Q', self.mmap, self.tail_offset, new_tail) def read_messages(self): """Ultra-fast direct memory read""" head = struct.unpack('Q', self.mmap[self.head_offset:self.head_offset+8])[0] tail = struct.unpack('Q', self.mmap[self.tail_offset:self.tail_offset+8])[0] messages = [] current = head while current < tail: try: # Read message length msg_len = struct.unpack('I', self.mmap[self.data_offset + current:self.data_offset + current + 4])[0] # Safety check if msg_len > self.buffer_size or msg_len <= 0: break # Read message data data = self.mmap[self.data_offset + current + 4:self.data_offset + current + 4 + msg_len] messages.append(data.decode()) current += 4 + msg_len except Exception as e: print(f"Error reading message: {e}") break # Update head pointer struct.pack_into('Q', self.mmap, self.head_offset, current) return messages def __del__(self): """Cleanup when object is destroyed""" self.stop_listening() if hasattr(self, 'mmap'): self.mmap.close() # Dave's ultra-fast hotel messaging in action hotel = MemoryMappedPubSub() # Define subscriber callbacks def pool_guest(message): print(f"🏊 Pool Guest received: {message}") def restaurant_guest(message): print(f"🍽️ Restaurant Guest received: {message}") # Subscribe to channels (automatically starts background listener) hotel.subscribe("pool", pool_guest) hotel.subscribe("restaurant", restaurant_guest) # Publish messages (ultra-fast memory writes) hotel.publish("pool", "Pool closing in 10 minutes!") hotel.publish("restaurant", "Happy hour starts now!") What makes this special: Բարձր արագ գրառումը: Direct memory writes, no system calls Automatic Message Routing: Background thread processes messages and calls abonnents (Ապլատոմսային հաղորդագրության ռեժիմ) Շատ սեղմիչներ մեկ Channel- ում: Ամեն Channel- ում կարող է լինել մի քանի սեղմիչներ: Հեղինակային տեղեկատվություն: One bad callback doesn’t crash the system Clean Resource Management: Ավտոմատ մաքրում, երբ կատարվում է Dave's Hotel- ը այժմ կարող է վերահսկել միլիոնավոր հաճախորդների հաղորդագրություններ մեկ շաբաթում, իսկ վերահսկել է հեշտ "բեռնել եւ մոռանալ" մոդել, որը իր համակարգը հայտնի է: Performance- ի համեմատություն Solution Messages/Second Use Case Complexity Basic Pub/Sub ~50K Small apps, prototypes ⭐ Simple Queued Pub/Sub ~200K Most production systems ⭐⭐ Moderate Memory-Mapped ~5M+ High-frequency trading, multi-process ⭐⭐⭐⭐⭐ Expert External (Redis) ~100K+ Distributed systems ⭐⭐⭐ Moderate Basic Pub/Sub 50K Small Apps, Պտոֆիլմներ Հեշտություն Queued Pub/Sub ~ 200 կ Շատ արտադրական համակարգեր Հիմնական Memory-Mapped ~ 5 մ + High Frequency Trading, Multi-Process առեւտրի External (Redis) ~ 100K + Distributed համակարգեր When to use each: Հիմնական: Ուսուցում, փոքր ծրագրեր, <10K հաղորդագրություններ / sec Կառուցված: Շատ իրական ծրագրեր, լավ աշխատում է տրանսպորտային փակները Memory-Mapped: >500K հաղորդագրություններ / sec, cross-process հաղորդագրություն, ultra-low latency Արդյունաբերական: Multiple servers, վերահսկողություն, proven reliability Ավելացնել սխալ վերահսկողություն, վերահսկողություն, եւ scaling, եւ դուք ունեք ինտերֆեսիոնալ հաղորդագրություն. Popular Pub/Sub տեխնոլոգիաներ Redis Pub/Sub: Հեշտ, արագ, մեծ է իրական ժամանակի գործառույթների համար Apache Kafka: Enterprise-grade, աշխատում է խոշոր ծախսերը RabbitMQ- ը: Բջջային հաղորդագրությունների հզորությունը եւ հզոր routing- ը Cloud լուծումներ: AWS SNS / SQS, Google Pub / Sub, Azure Service Bus Dave- ի պատմության վերջը Երկու ամիս հետո, Dave-ին «Chief Communication Innovation Officer»-ին առաջարկել է, քանի որ հաճախորդների հավասարության ստանդարտները կանգնած են. Dave- ը նույնիսկ կարծում է, որ «սենալներ» նշանակում են Hotel- ի սենյակային TV համակարգը, բայց իր intercom- ի սենյակները ուսուցում են համակարգչային գիտության ուսանողներին ամբողջ աշխարհում, թե ինչպես աշխատում են հաղորդագրության մոդելներ: Երկու օրվա երկու անգամ ճիշտ է, եւ նույնիսկ Dave- ը կարող է բաղկացած լինել լավ դիզայնի մեջ, եթե առաջին անգամ անում է մի քանի բան: Նա վերադառնալ է այն, ինչ նա գիտի լավագույնը - փոխանցման համակարգեր. իր նոր գործառույթը վերլուծում է ծովային անձնական փոխանցման հետ «Այբոմսերը», որոնք աշխատում են «Data Busses- ում». And what about Dave? Երբ հարցվում է տեխնիկական դիզայնի մասին, Dave հպարտորեն բացահայտում է: «Այս դիզայնը արտադրում է իր տեղադրման տեղը ուղեւորների համար, ովքեր գրանցում են հատուկ ռեժիմերի համար: Դա pub/sub, բայց համար դիզայնի համար! Քաղաքային փոխանցման կենտրոնը դեռ փորձում է տեսնել, թե նա հին է, թե՞ պետք է վերցնել իր բիզնես լիցենզիանը: Dave- ը դեռ հավատում է, որ նա լուծում է «լուսանկարներ» Dave- ի նոր համակարգի հաջողությունը այնքան խուսափել է, որ նա խուսափել է եւ սկսել է նոր բիզնեսը: Հաջորդ անգամ, երբ դուք ձեր տեղական խուսափման խողովակում եք, դուք կարող եք տեսնել նոր «Pub Sub» - որը տեսնում է Dave- ի ռեժիմիական «այսինկրոնորեն մշակված մանրաթելային սննդի սննդի սննդի սննդի հետ, որոնք չի բլոգում սննդի գծերը». Նա դեռ ստանում է տիկնիկների տիկնիկները հյուրանոցից.