Yazılım mimarisindeki modeller: Reaktör modeli
Modeller, modern yazılımın geliştirilmesinde ve yazılımın mimarisinde önemli bir soyutlamadır. Açıkça tanımlanmış terminoloji, temiz dokümantasyon ve öğrenme en iyisinden sunarlar. Sunucu veya GUI gibi olaylar tarafından kontrol edilen uygulamalar genellikle reaktör mimarlık modelini kullanır. Bu, farklı istekleri aynı anda kabul edebilir ve bunları farklı tüccarlara dağıtabilir.
Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
Reaktör modeli, Demultylex'te hizmet taleplerini dağıtmak için ve aynı zamanda çeşitli hizmet sağlayıcılara hizmet taleplerini dağıtmak için olaylar tarafından kontrol edilen bir çerçevedir. Araştırmalar eşzamanlı olarak işlenir.
Reaktör
Olarak da bilinir
sorun
Bir sunucu olmalı
Çözüm
Handles
Reaktör
Bir reaktörün dinamik davranışı oldukça ilginçtir.
Dinamik davranış
Aşağıdaki noktalar, reaktör ile olayların yöneticisi arasındaki kontrol akışını göstermektedir:
Örnek
Bu örnekte, küçük çerçeve kullanılır. “Kitapçılar Little C ++, ağ tabanlı uygulamalar ve masaüstü, sunucu, mobil, IoT ve üretim sisteminde çalışan internetin oluşturulması için güçlü C ++ çok platformlu kitaplıklardır.“
// reactor.cpp
#include <fstream>
#include <string>
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Observer.h"
#include "Poco/Thread.h"
#include "Poco/Util/ServerApplication.h"
using Poco::Observer;
using Poco::Thread;
using Poco::Net::ReadableNotification;
using Poco::Net::ServerSocket;
using Poco::Net::ShutdownNotification;
using Poco::Net::SocketAcceptor;
using Poco::Net::SocketReactor;
using Poco::Net::StreamSocket;
using Poco::Util::Application;
class EchoHandler {
public:
EchoHandler(const StreamSocket& s,
SocketReactor& r): socket(s), reactor(r) { // (11)
reactor.addEventHandler(socket,
Observer<EchoHandler, ReadableNotification>
(*this, &EchoHandler::socketReadable));
}
void socketReadable(ReadableNotification*) {
char buffer[8];
int n = socket.receiveBytes(buffer, sizeof(buffer));
if (n > 0) {
socket.sendBytes(buffer, n); // (13)
}
else {
reactor.removeEventHandler(socket, // (12)
Observer<EchoHandler,
ReadableNotification>
(*this, &EchoHandler::socketReadable));
delete this;
}
}
private:
StreamSocket socket;
SocketReactor& reactor;
};
class DataHandler {
public:
DataHandler(StreamSocket& s,
SocketReactor& r):
socket(s), reactor(r), outFile("reactorOutput.txt") {
reactor.addEventHandler(socket, // (14)
Observer<DataHandler,
ReadableNotification>
(*this, &DataHandler::socketReadable));
reactor.addEventHandler(socket, // (15)
Observer<DataHandler,
ShutdownNotification>
(*this, &DataHandler::socketShutdown));
socket.setBlocking(false);
}
~DataHandler() { // (16)
reactor.removeEventHandler(socket,
Observer<DataHandler,
ReadableNotification>
(*this, &DataHandler::socketReadable));
reactor.removeEventHandler(socket,
Observer<DataHandler,
ShutdownNotification>
(*this, &DataHandler::socketShutdown));
}
void socketReadable(ReadableNotification*) {
char buffer[64];
int n = 0;
do {
n = socket.receiveBytes(&buffer[0], sizeof(buffer));
if (n > 0) {
std::string s(buffer, n);
outFile << s << std::flush; // (17)
}
else break;
} while (true);
}
void socketShutdown(ShutdownNotification*) {
delete this;
}
private:
StreamSocket socket;
SocketReactor& reactor;
std:
fstream outFile;
};
class Server: public Poco::Util::ServerApplication {
protected:
void initialize(Application& self) { // (3)
ServerApplication::initialize(self);
}
void uninitialize() { // (4)
ServerApplication::uninitialize();
}
int main(const std::vector<std::string>&) { // (2)
ServerSocket serverSocketEcho(4711); // (5)
ServerSocket serverSocketData(4712); // (6)
SocketReactor reactor;
SocketAcceptor<EchoHandler>
acceptorEcho(serverSocketEcho, reactor); // (7)
SocketAcceptor<DataHandler>
acceptorData(serverSocketData, reactor); // (8)
Thread thread;
thread.start(reactor); // (9)
waitForTerminationRequest();
reactor.stop(); // (10)
thread.join();
return Application::EXIT_OK;
}
};
int main(int argc, char** argv) {
Server app; // (1)
return app.run(argc, argv);
}
(1) TCP sunucusunu oluşturun. Bu getiriyor main-Kunksiyon (2) ve (3) ve (4) 'de sizinkinden başlatılır. . main-TCP sunucusunun phonction, kapı 4711 5) ve Porta 4712 (6) 'ı dinleyen iki sunucu soketi oluşturur. (7) ve (5) 'de sunucu soketleri EchoHandler Ve bu DataHandler oluşturuldu. . SocketAcceptor Modella Tasarım konnektörü tasarım modelinin alıcı bileşeni. Reaktör, yıkım talebini alana kadar ayrı bir iş parçacığında (9) çalışır (10).
. EchoHandler Okuma ticaretini üreticiye kaydetti (11) ve okuma kolunun kaydını üye işlevine yükseltiyor socketReadable Su (12). Müşterinin mesajını döndürür (13). Aksine, DataHandler Verileri sunucuya aktarmak için bir istemci. . Handler Okuma etkinlikleri (14) ve üreticisindeki söndürme etkinlikleri için eylemini kaydeder (satır 15). İkisi birden Handler Ben muhripteyim DataHandler (16) Yine Deregister. Veri iletiminin sonucu doğrudan dosya tutamağındadır outFile Yazılı (17).
Aşağıdaki sürümde sol sunucuyu ve sağdaki iki istemciyi gösterir. Bir müşteri oturumu müşteri görevi görür. İlk müşteri kapıya bağlanır 4711: telnet 127.0.0.1 4711. Bu istemci ECHO sunucusuna bağlanır ve bu nedenle isteğinizi gösterir. İkinci müşteri kapıya bir bağlantı kurar 4712: telnet 127.0.0.1 4712. Sunucu çıkışı, istemci verilerinin sunucuya aktarıldığını gösterir.
Reaktörün avantajları ve dezavantajları nelerdir?
Avantajlar ve dezavantajlar
Avantajlar
Yarışma alanında kullanılan birçok kanıtlanmış model vardır. Paylaşım ve mutasyon gibi senkronizasyon sorunları, aynı zamanda yardımcı mimarilerle de ilgilenirler. Bir sonraki yazımda, verilerin ortak kullanımına odaklanan modellerle başlıyorum.
(RME)
Ne yazık ki, bu bağlantı artık geçerli değil.
Boşa harcanan eşyalara olan bağlantılar, 7 günlük daha büyükse veya çok sık çağrılmışsa gerçekleşmez.
Bu makaleyi okumak için bir Haberler+ paketine ihtiyacınız var. Şimdi yükümlülük olmadan bir hafta deneyin – yükümlülük olmadan!
Yazılım mimarisindeki modeller: Reaktör modeli
Modeller, modern yazılımın geliştirilmesinde ve yazılımın mimarisinde önemli bir soyutlamadır. Açıkça tanımlanmış terminoloji, temiz dokümantasyon ve öğrenme en iyisinden sunarlar. Sunucu veya GUI gibi olaylar tarafından kontrol edilen uygulamalar genellikle reaktör mimarlık modelini kullanır. Bu, farklı istekleri aynı anda kabul edebilir ve bunları farklı tüccarlara dağıtabilir.

Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.

Reaktör modeli, Demultylex'te hizmet taleplerini dağıtmak için ve aynı zamanda çeşitli hizmet sağlayıcılara hizmet taleplerini dağıtmak için olaylar tarafından kontrol edilen bir çerçevedir. Araştırmalar eşzamanlı olarak işlenir.
Reaktör
Olarak da bilinir
sorun
Bir sunucu olmalı
- Aynı anda farklı müşterilere cevap verin,
- performans sergiliyor, istikrarlı ve ölçeklenebilir
- Yeni veya geliştirilmiş hizmetleri destekleyecek şekilde genişletilebilir.
Çözüm
- Desteklenen her hizmet bir yöneticide kapsüllenir.
- Tüccarlar reaktöre kaydedilir.
- Reaktör, gelen tüm olaylar için senkronize beklemek için bir Demultiplexer etkinliği kullanır.
- Reaktör bilgilendirilirse, hizmet gereksinimini ilgili yöneticiye iletir.


Handles
- Kulplar, ağ bağlantıları, açık dosyalar veya GUI olayları gibi farklı olay kaynaklarını tanımlar.
- Olayların kaynağı, ilişkili yönetim üzerinde sıralanan bağlantı, okuma veya yazma gibi olaylar yaratır.
- Demultixer senkron etkinliği, ilişkili ACT olayı geliştirene kadar bir veya daha fazla olay ve gösterge bloğunu bekliyor.
- Seçilen sistem çağrıları, anketler, epoll, kqueue veya waitFormultipplebject ile gösterge verici olayları bekleyebilir.
- Etkinlik Yöneticisi, endikasyon olaylarının geliştirilmesi için arayüzü tanımlar.
- Etkinlik Yöneticisi, uygulamanın desteklenen hizmetlerini tanımlar.
- Beton Etkinlik Yöneticisi, Etkinlik Yöneticisi tarafından tanımlanan uygulama arayüzünü uygular.
Reaktör
- Dosya komut dosyaları yardımıyla belirli etkinlikler operatörünün kaydı ve kaydı için bir arayüzü destekler,
- Göstergeci olayları beklemek için Derultlexer senkron bir olay kullanın; Bir gösterge olayı okuma, yazma veya hata olayı olabilir,
- Belirli etkinliklerin yöneticinize etkinlikler atayın e
- Yaşam döngüsünün süresini yönetir.
Bir reaktörün dinamik davranışı oldukça ilginçtir.
Dinamik davranış
Aşağıdaki noktalar, reaktör ile olayların yöneticisi arasındaki kontrol akışını göstermektedir:
- Uygulama, reaktördeki belirli etkinlikler için bir etkinlik yöneticisi kaydeder.
- Her etkinlik yöneticisi reaktörü özel yöneticisini sağlar.
- Uygulama olayların döngüsünü başlatır. Etkinliğin döngüsü gösterge niteliğinde olayları bekliyor.
- Bir olay kaynağı hazır olduğunda DepultLexer olayı reaktöre döner.
- Reaktör tutamaçları ilgili etkinlik yöneticisine gönderir.
- Etkinlik Yöneticisi etkinliği detaylandırır.
Örnek
Bu örnekte, küçük çerçeve kullanılır. “Kitapçılar Little C ++, ağ tabanlı uygulamalar ve masaüstü, sunucu, mobil, IoT ve üretim sisteminde çalışan internetin oluşturulması için güçlü C ++ çok platformlu kitaplıklardır.“
// reactor.cpp
#include <fstream>
#include <string>
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Observer.h"
#include "Poco/Thread.h"
#include "Poco/Util/ServerApplication.h"
using Poco::Observer;
using Poco::Thread;
using Poco::Net::ReadableNotification;
using Poco::Net::ServerSocket;
using Poco::Net::ShutdownNotification;
using Poco::Net::SocketAcceptor;
using Poco::Net::SocketReactor;
using Poco::Net::StreamSocket;
using Poco::Util::Application;
class EchoHandler {
public:
EchoHandler(const StreamSocket& s,
SocketReactor& r): socket(s), reactor(r) { // (11)
reactor.addEventHandler(socket,
Observer<EchoHandler, ReadableNotification>
(*this, &EchoHandler::socketReadable));
}
void socketReadable(ReadableNotification*) {
char buffer[8];
int n = socket.receiveBytes(buffer, sizeof(buffer));
if (n > 0) {
socket.sendBytes(buffer, n); // (13)
}
else {
reactor.removeEventHandler(socket, // (12)
Observer<EchoHandler,
ReadableNotification>
(*this, &EchoHandler::socketReadable));
delete this;
}
}
private:
StreamSocket socket;
SocketReactor& reactor;
};
class DataHandler {
public:
DataHandler(StreamSocket& s,
SocketReactor& r):
socket(s), reactor(r), outFile("reactorOutput.txt") {
reactor.addEventHandler(socket, // (14)
Observer<DataHandler,
ReadableNotification>
(*this, &DataHandler::socketReadable));
reactor.addEventHandler(socket, // (15)
Observer<DataHandler,
ShutdownNotification>
(*this, &DataHandler::socketShutdown));
socket.setBlocking(false);
}
~DataHandler() { // (16)
reactor.removeEventHandler(socket,
Observer<DataHandler,
ReadableNotification>
(*this, &DataHandler::socketReadable));
reactor.removeEventHandler(socket,
Observer<DataHandler,
ShutdownNotification>
(*this, &DataHandler::socketShutdown));
}
void socketReadable(ReadableNotification*) {
char buffer[64];
int n = 0;
do {
n = socket.receiveBytes(&buffer[0], sizeof(buffer));
if (n > 0) {
std::string s(buffer, n);
outFile << s << std::flush; // (17)
}
else break;
} while (true);
}
void socketShutdown(ShutdownNotification*) {
delete this;
}
private:
StreamSocket socket;
SocketReactor& reactor;
std:
};
class Server: public Poco::Util::ServerApplication {
protected:
void initialize(Application& self) { // (3)
ServerApplication::initialize(self);
}
void uninitialize() { // (4)
ServerApplication::uninitialize();
}
int main(const std::vector<std::string>&) { // (2)
ServerSocket serverSocketEcho(4711); // (5)
ServerSocket serverSocketData(4712); // (6)
SocketReactor reactor;
SocketAcceptor<EchoHandler>
acceptorEcho(serverSocketEcho, reactor); // (7)
SocketAcceptor<DataHandler>
acceptorData(serverSocketData, reactor); // (8)
Thread thread;
thread.start(reactor); // (9)
waitForTerminationRequest();
reactor.stop(); // (10)
thread.join();
return Application::EXIT_OK;
}
};
int main(int argc, char** argv) {
Server app; // (1)
return app.run(argc, argv);
}
(1) TCP sunucusunu oluşturun. Bu getiriyor main-Kunksiyon (2) ve (3) ve (4) 'de sizinkinden başlatılır. . main-TCP sunucusunun phonction, kapı 4711 5) ve Porta 4712 (6) 'ı dinleyen iki sunucu soketi oluşturur. (7) ve (5) 'de sunucu soketleri EchoHandler Ve bu DataHandler oluşturuldu. . SocketAcceptor Modella Tasarım konnektörü tasarım modelinin alıcı bileşeni. Reaktör, yıkım talebini alana kadar ayrı bir iş parçacığında (9) çalışır (10).
. EchoHandler Okuma ticaretini üreticiye kaydetti (11) ve okuma kolunun kaydını üye işlevine yükseltiyor socketReadable Su (12). Müşterinin mesajını döndürür (13). Aksine, DataHandler Verileri sunucuya aktarmak için bir istemci. . Handler Okuma etkinlikleri (14) ve üreticisindeki söndürme etkinlikleri için eylemini kaydeder (satır 15). İkisi birden Handler Ben muhripteyim DataHandler (16) Yine Deregister. Veri iletiminin sonucu doğrudan dosya tutamağındadır outFile Yazılı (17).
Aşağıdaki sürümde sol sunucuyu ve sağdaki iki istemciyi gösterir. Bir müşteri oturumu müşteri görevi görür. İlk müşteri kapıya bağlanır 4711: telnet 127.0.0.1 4711. Bu istemci ECHO sunucusuna bağlanır ve bu nedenle isteğinizi gösterir. İkinci müşteri kapıya bir bağlantı kurar 4712: telnet 127.0.0.1 4712. Sunucu çıkışı, istemci verilerinin sunucuya aktarıldığını gösterir.

Reaktörün avantajları ve dezavantajları nelerdir?
Avantajlar ve dezavantajlar
Avantajlar
- Uygulamanın çerçevesi ve mantığı arasında açık bir ayrım.
- Belirli olayların çeşitli yöneticilerinin modülerliği.
- Reaktör farklı platformlara getirilebilir, çünkü seçim, anket, epoll, kqueue veya waitFormultiletpleObjects gibi olayların altta yatan işlevleri Unix (Select, Epoll) ve Windows platformlarında (WaitFormultipleObjects) mevcuttur.
- Arayüzün ve uygulamanın ayrılması, hizmetlerin kolay düzenlenmesini veya genişletilmesini sağlar.
- Genel mimari paralel yürütmeyi destekler.
- Reaktör, olayların olayları için bir sistem isteği gerektirir.
- Uzun zamandır bir etkinlik yöneticisi reaktörü engelleyebilir.
- Kontrolün tersine çevrilmesi testler ve hata ayıklama yapar.
Yarışma alanında kullanılan birçok kanıtlanmış model vardır. Paylaşım ve mutasyon gibi senkronizasyon sorunları, aynı zamanda yardımcı mimarilerle de ilgilenirler. Bir sonraki yazımda, verilerin ortak kullanımına odaklanan modellerle başlıyorum.
(RME)
Ne yazık ki, bu bağlantı artık geçerli değil.
Boşa harcanan eşyalara olan bağlantılar, 7 günlük daha büyükse veya çok sık çağrılmışsa gerçekleşmez.
Bu makaleyi okumak için bir Haberler+ paketine ihtiyacınız var. Şimdi yükümlülük olmadan bir hafta deneyin – yükümlülük olmadan!