Hacker News

Połączyliśmy jednowątkowy C++ z wielowątkowym Rustem

Połączyliśmy jednowątkowy C++ z wielowątkowym Rustem Ta kompleksowa analiza ofert interfejsowych zawiera szczegółowe badanie — Mewayz Business OS.

5 min. przeczytaj

Mewayz Team

Editorial Team

Hacker News

Oto pełny wpis na blogu poświęconym SEO:

Połączyliśmy jednowątkowy C++ z wielowątkową rdzą

Łączenie jednowątkowego kodu C++ z wielowątkowym językiem Rust jest nie tylko możliwe — to jeden z najbardziej praktycznych sposobów modernizacji starszych systemów bez konieczności pełnego przepisywania. W firmie Mewayz sprostaliśmy dokładnie temu wyzwaniu podczas skalowania naszego biznesowego systemu operacyjnego składającego się z 207 modułów do obsługi 138 000 użytkowników, a wyniki zasadniczo zmieniły sposób, w jaki myślimy o interoperacyjności systemów.

Dlaczego miałbyś łączyć jednowątkowy C++ z wielowątkową rdzą?

Większość systemów produkcyjnych zawiera lata sprawdzonego w boju kodu C++. Przepisanie wszystkiego w Rust brzmi atrakcyjnie na papierze, ale wiąże się z ogromnym ryzykiem i miesiącami pracy inżynieryjnej. Pragmatyczne podejście polega na adopcji przyrostowej — opakowaniu istniejącej logiki C++ przy jednoczesnym przeniesieniu obciążeń wymagających dużej współbieżności do modelu własności Rusta.

W naszym przypadku podstawowe moduły logiki biznesowej działały niezawodnie w jednowątkowym C++ przez lata. Zajmowali się sekwencyjnym przetwarzaniem zadań, generowaniem dokumentów i obliczeniami finansowymi. Ponieważ jednak liczba naszych użytkowników przekroczyła 100 tys., potrzebowaliśmy równoległego przetwarzania danych, jednoczesnej obsługi interfejsów API i bezpiecznego zarządzania stanem współdzielonym. Funkcje Send i Sync Rusta dały nam gwarancje współbieżności w czasie kompilacji, których C++ po prostu nie mógłby zaoferować bez obszernego ręcznego audytu.

Kluczową motywacją jest redukcja ryzyka. Zachowujesz to, co działa, i dodajesz skalowanie — bez narażania całej bazy kodu na migrację, która może nigdy się nie zakończyć.

Jak faktycznie działa granica FFI?

Interfejs funkcji obcych (FFI) pomiędzy C++ i Rustem działa poprzez sygnatury funkcji zgodne z C. Zewnętrzne bloki „C” Rusta udostępniają funkcje, które C++ może wywołać bezpośrednio i odwrotnie. Krytyczne wyzwanie pojawia się, gdy wielowątkowe środowisko wykonawcze Rusta musi bezpiecznie wywoływać jednowątkowy kod C++.

Rozwiązaliśmy ten problem, stosując dedykowaną architekturę:

Executor C++ ograniczony do wątków: wszystkie wywołania C++ są kierowane przez jeden dedykowany wątek przy użyciu kanału przekazywania komunikatów, co gwarantuje, że niezmiennik jednowątkowy nigdy nie zostanie naruszony.

💡 CZY WIESZ?

Mewayz replaces 8+ business tools in one platform

CRM · Fakturowanie · HR · Projekty · Rezerwacje · eCommerce · POS · Analityka. Darmowy plan dostępny na zawsze.

Zacznij za darmo →

Warstwa asynchronicznego mostu Rust: zadania Tokio przesyłają pracę do modułu wykonującego C++ i oczekują na wyniki za pośrednictwem kanałów one-shot, utrzymując stronę Rust w pełni asynchroniczną.

Zarządzanie nieprzezroczystymi wskaźnikami: obiekty C++ są opakowane w struktury Rust, które implementują Drop w celu deterministycznego czyszczenia, zapobiegając wyciekom pamięci poza granicę języka.

Serializacja na granicy: złożone struktury danych są serializowane do buforów FlatBuffers w warstwie FFI, co pozwala uniknąć delikatnego dopasowywania układu struktur i umożliwia niezależną ewolucję każdej strony.

Izolacja paniki: catch_unwind Rusta otacza każdy punkt wejścia FFI, tak że panika nigdy nie przekracza granicy języka, co byłoby niezdefiniowanym zachowaniem.

Ten wzorzec zapewnił nam przepustowość wielowątkowego Rusta z niezawodnością sprawdzonej logiki C++ — bez przepisywania ani jednej linii oryginalnych reguł biznesowych.

Jakich największych pułapek należy unikać?

Najbardziej niebezpiecznym błędem jest założenie, że kod C++ jest bezpieczny dla wątków, choć tak nie jest. Stan globalny, zmienne statyczne i wywołania bibliotek bez współbieżności spowodują wyścigi danych, których kompilator Rusta nie będzie w stanie wykryć poza granicami FFI. Bezpieczeństwo Rusta gwarantuje zatrzymanie się w niebezpiecznym bloku — za wszystko w środku odpowiadasz Ty.

Kluczowy spostrzeżenie: Rust gwarantuje bezpieczeństwo pamięci w ramach własnego kodu, ale w momencie przekroczenia granicy FFI w C++, dziedziczysz wszystkie problemy związane z bezpieczeństwem wątków, jakie ma C++. Architektura wokół tej granicy ma większe znaczenie niż kod po obu jej stronach.

Inną częstą pułapką jest zarządzanie przez całe życie. Obiekty C++ nie biorą udziału w sprawdzaniu pożyczek Rusta. Jeśli Rust upuści referencję, podczas gdy C++ nadal trzyma wskaźnik, pojawią się błędy, które są niezwykle trudne do zdiagnozowania. Rozwiązaliśmy ten problem, wymuszając ścisłą semantykę własności: obiekty C++ są zawsze własnością dokładnie jednego opakowania Rusta, a dostęp współdzielony odbywa się poprzez zliczanie referencji w oparciu o Arc po stronie Rusta.

Pod względem wydajności, doskonałe

Build Your Business OS Today

From freelancers to agencies, Mewayz powers 138,000+ businesses with 207 integrated modules. Start free, upgrade when you grow.

Create Free Account →

Wypróbuj Mewayz za Darmo

Kompleksowa platforma dla CRM, fakturowania, projektów, HR i więcej. Karta kredytowa nie jest wymagana.

Powiązany przewodnik

Przewodnik po zarządzaniu HR →

Manage your team effectively: employee profiles, leave management, payroll, and performance reviews.

Zacznij dziś zarządzać swoją firmą mądrzej.

Dołącz do 30,000+ firm. Plan darmowy na zawsze · Bez karty kredytowej.

Uznałeś to za przydatne? Udostępnij to.

Gotowy, aby wprowadzić to w życie?

Dołącz do 30,000+ firm korzystających z Mewayz. Darmowy plan forever — karta kredytowa nie jest wymagana.

Rozpocznij darmowy okres próbny →

Gotowy, by podjąć działanie?

Rozpocznij swój darmowy okres próbny Mewayz dziś

Platforma biznesowa wszystko w jednym. Karta kredytowa nie jest wymagana.

Zacznij za darmo →

14-dniowy darmowy okres próbny · Bez karty kredytowej · Anuluj w dowolnym momencie