2011-01-16 6 views
21

यह प्रश्न मुझे कुछ समय के लिए परेशान करता है (मुझे आशा है कि मैं केवल एक ही नहीं हूं)। मैं एक सामान्य 3-स्तरीय जावा ईई ऐप लेना चाहता हूं और देख सकता हूं कि यह संभवतः अभिनेताओं के साथ कैसे लागू किया जा सकता है। मैं यह जानना चाहता हूं कि क्या यह वास्तव में इस तरह के संक्रमण को करने के लिए कोई समझ में आता है और अगर इससे समझ में आता है तो मैं इसका लाभ कैसे प्राप्त कर सकता हूं (शायद प्रदर्शन, बेहतर वास्तुकला, विस्तारशीलता, रखरखाव, आदि ...)।अभिनेताओं को सामान्य 3-स्तरीय आर्किटेक्चर स्थानांतरित करना

trait UserDao { 
    def getUsers(): List[User] 
    def getUser(id: Int): User 
    def addUser(user: User) 
} 

trait UserService { 
    def getUsers(): List[User] 
    def getUser(id: Int): User 
    def addUser(user: User): Unit 

    @Transactional 
    def makeSomethingWithUsers(): Unit 
} 


@Controller 
class UserController { 
    @Get 
    def getUsers(): NodeSeq = ... 

    @Get 
    def getUser(id: Int): NodeSeq = ... 

    @Post 
    def addUser(user: User): Unit = { ... } 
} 

आप कई वसंत अनुप्रयोगों में कुछ इस तरह पा सकते हैं:

यहाँ ठेठ नियंत्रक (प्रस्तुति), सेवा (व्यवसाय तर्क), डीएओ (डेटा) कर रहे हैं। हम सरल कार्यान्वयन कर सकते हैं जिसमें कोई साझा स्थिति नहीं है और ऐसा इसलिए है क्योंकि इसमें सिंक्रनाइज़ किए गए ब्लॉक नहीं हैं ... इसलिए सभी राज्य डेटाबेस में हैं और एप्लिकेशन लेनदेन पर निर्भर करता है। सेवा, नियंत्रक और दाओ के पास केवल एक उदाहरण है। तो प्रत्येक अनुरोध के लिए आवेदन सर्वर अलग थ्रेड का उपयोग करेगा, लेकिन धागे एक दूसरे को अवरुद्ध नहीं करेंगे (लेकिन डीबी आईओ द्वारा अवरुद्ध किया जाएगा)।

मान लीजिए कि हम अभिनेताओं के साथ समान कार्यक्षमता को लागू करने की कोशिश कर रहे हैं। यह इस तरह दिख सकता है:

sealed trait UserActions 
case class GetUsers extends UserActions 
case class GetUser(id: Int) extends UserActions 
case class AddUser(user: User) extends UserActions 
case class MakeSomethingWithUsers extends UserActions 

val dao = actor { 
    case GetUsers() => ... 
    case GetUser(userId) => ... 
    case AddUser(user) => ... 
} 

val service = actor { 
    case GetUsers() => ... 
    case GetUser(userId) => ... 
    case AddUser(user) => ... 
    case MakeSomethingWithUsers() => ... 
} 

val controller = actor { 
    case Get("/users") => ... 
    case Get("/user", userId) => ... 
    case Post("/add-user", user) => ... 
} 

मुझे लगता है कि यह बहुत महत्वपूर्ण नहीं है कि कैसे() और पोस्ट() निकालने वाले यंत्र लागू किए जाते हैं। मान लीजिए कि मैं इसे लागू करने के लिए एक ढांचा लिखता हूं। मैं इस तरह नियंत्रक को संदेश भेज सकता हूं:

controller !! Get("/users") 

वही बात नियंत्रक और सेवा द्वारा की जाएगी। इस मामले में पूरा वर्कफ़्लो तुल्यकालिक होगा। इससे भी बदतर - मैं समय पर केवल एक ही अनुरोध को संसाधित कर सकता हूं (इस बीच सभी अन्य अनुरोध नियंत्रक के मेलबॉक्स में उतरेंगे)। तो मुझे इसे सभी असीमित बनाने की जरूरत है।

क्या इस सेटअप में प्रत्येक प्रोसेसिंग चरण को असीमित रूप से करने का कोई शानदार तरीका है?

जहां तक ​​मैं समझता हूं कि प्रत्येक स्तर को किसी संदेश को उस संदेश के संदर्भ को सहेजना चाहिए जो उसे प्राप्त होता है और फिर नीचे दिए गए स्तर पर संदेश भेजता है। जब कुछ परिणाम संदेश के साथ जवाब के नीचे स्तर होता है तो मुझे प्रारंभिक संदर्भ को पुनर्स्थापित करने और मूल प्रेषक को इस परिणाम के साथ उत्तर देने में सक्षम होना चाहिए। क्या ये सही है?

इसके अलावा, इस समय मेरे पास प्रत्येक स्तर के लिए अभिनेता का केवल एक उदाहरण है। भले ही वे असीमित रूप से काम करेंगे, फिर भी मैं समानांतर केवल एक नियंत्रक, सेवा और दाओ संदेश में संसाधित कर सकता हूं। इसका मतलब है कि मुझे एक ही प्रकार के अधिक अभिनेताओं की आवश्यकता है। जो मुझे प्रत्येक स्तर के लिए लोडबैलेंसर की ओर ले जाता है। इसका मतलब यह भी है कि अगर मेरे पास UserService और ItemService है तो मुझे लोडबेलस दोनों अलग-अलग होना चाहिए।

मुझे लगता है कि मैं कुछ गलत समझता हूं। सभी आवश्यक विन्यास को अधूरा लगता है। आप इस बारे में क्या सोचते हैं?

(पुनश्च: यह भी बहुत पता है कि कैसे डीबी लेनदेन इस तस्वीर में फिट दिलचस्प होगा, लेकिन मुझे लगता है कि इस सूत्र के लिए overkill है)

+0

+1 - आपके द्वारा महत्वाकांक्षी सामान, आसान एंजेल। – duffymo

उत्तर

4

बड़े गणना गहन परमाणु लेनदेन मुश्किल कर रहे हैं बंद खींचने के लिए है, जो एक कारण है कि डेटाबेस इतने लोकप्रिय क्यों हैं। इसलिए यदि आप पूछ रहे हैं कि क्या आप डेटाबेस की सभी लेनदेन और अत्यधिक-स्केलेबल विशेषताओं को बदलने के लिए पारदर्शी रूप से और आसानी से कलाकारों का उपयोग कर सकते हैं (जिसका शक्ति आप जावा ईई मॉडल में बहुत अधिक झुकाव कर रहे हैं), तो जवाब नहीं है।

लेकिन कुछ चालें आप खेल सकते हैं।उदाहरण के लिए, यदि एक अभिनेता एक बाधा उत्पन्न कर रहा है, लेकिन आप एक प्रेषक/कार्यकर्ता कृषि संरचना बनाने के प्रयास में नहीं जाना चाहते हैं, तो आप गहन कार्य को वायदा में स्थानांतरित करने में सक्षम हो सकते हैं:

val service = actor { 
    ... 
    case m: MakeSomethingWithUsers() => 
    Futures.future { sender ! myExpensiveOperation(m) } 
} 

इस तरह, वास्तव में महंगे कार्यों को नए धागे में फेंक दिया जाता है (यह मानते हुए कि आपको परमाणुता और डेडलॉक्स और इतने पर चिंता करने की आवश्यकता नहीं है, लेकिन फिर भी, इन समस्याओं को हल करना आम तौर पर आसान नहीं है) और जहां भी उन्हें जाना चाहिए, वहां संदेशों को भेज दिया जाता है।

+0

बेशक जब तक आप एक सर्वर पर ऐसे धागे नहीं कर सकते हैं। फिर आपका समाधान खराब पैमाने पर होगा। – wheaties

+1

@wheaties: वास्तव में। आपका डेटाबेस प्रदर्शन भी मशीन पर बहुत अप्रत्याशित होगा। –

5

बस riffing, लेकिन ...

मुझे लगता है कि आप अभिनेताओं उपयोग करना चाहते हैं, तो आप दूर सभी पिछले पैटर्न फेंक और कुछ नया करने की कल्पना करना चाहिए, तो शायद फिर से शामिल पुराने पैटर्न (नियंत्रक, दाव, आदि) अंतराल को भरने के लिए आवश्यक है।

उदाहरण के लिए, यदि प्रत्येक उपयोगकर्ता कई अन्य JVMs में JVM में या रिमोट एक्टर्स के माध्यम से एक व्यक्तिगत अभिनेता है, तो क्या होगा। प्रत्येक उपयोगकर्ता अद्यतन संदेश प्राप्त करने, अपने बारे में डेटा प्रकाशित करने और डिस्क (या डीबी या मोंगो या कुछ) में सहेजने के लिए ज़िम्मेदार है।

मुझे लगता है कि मुझे जो मिल रहा है वह यह है कि आपकी सभी राज्यिक वस्तुएं अभिनेताओं के लिए सिर्फ संदेशों को अपडेट करने का इंतजार कर सकती हैं।

(HTTP के लिए (यदि आप इसे स्वयं लागू करना चाहते हैं), प्रत्येक अनुरोध एक ऐसे अभिनेता को जन्म देता है जो तब तक ब्लॉक करता है जब तक कि इसका जवाब न हो (इसका उपयोग कर रहा हो? या भविष्य), जिसे बाद में प्रतिक्रिया में स्वरूपित किया जाता है। आप एक स्पोन कर सकते हैं इस तरह के कलाकारों के बहुत सारे, मुझे लगता है।)

जब उपयोगकर्ता "[email protected]" के लिए पासवर्ड बदलने के लिए कोई अनुरोध आता है, तो आप '[email protected]' पर एक संदेश भेजते हैं! ChangePassword ("नया गुप्त")।

या आपके पास एक निर्देशिका प्रक्रिया है जो सभी उपयोगकर्ता कलाकारों के स्थानों का ट्रैक रखती है। UserDirectory अभिनेता एक अभिनेता (एक जेवीएम प्रति) हो सकता है जो संदेश प्राप्त करता है कि कौन से उपयोगकर्ता कलाकार वर्तमान में चल रहे हैं और उनके नाम क्या हैं, फिर अनुरोध अभिनेताओं से उन्हें संदेश भेजते हैं, अन्य संघीय निर्देशिका कलाकारों को प्रतिनिधि देते हैं। आप UserDirectory से पूछेंगे जहां उपयोगकर्ता है, और फिर उस संदेश को सीधे भेजें। यदि उपयोगकर्ता पहले से नहीं चल रहा है तो उपयोगकर्ता अभिनेता अभिनेता उपयोगकर्ता अभिनेता शुरू करने के लिए ज़िम्मेदार है। उपयोगकर्ता अभिनेता अपने राज्य को पुनः प्राप्त करता है, फिर अद्यतनों को छोड़ देता है।

आदि, और इसी तरह।

इस बारे में सोचना मजेदार है। उदाहरण के लिए, प्रत्येक उपयोगकर्ता अभिनेता डिस्क पर, एक निश्चित समय के बाद समय निकाल सकता है, और यहां तक ​​कि एकत्रीकरण कलाकारों को संदेश भेज सकता है। उदाहरण के लिए, एक उपयोगकर्ता अभिनेता LastAccess अभिनेता को एक संदेश भेज सकता है। या पासवर्डटाइमआउट एक्टर सभी उपयोगकर्ता कलाकारों को संदेश भेज सकता है, अगर उन्हें एक निश्चित तिथि से पुराना पासवर्ड हो तो पासवर्ड बदलने की आवश्यकता होती है। उपयोगकर्ता अभिनेता स्वयं को अन्य सर्वरों पर भी क्लोन कर सकते हैं, या स्वयं को कई डेटाबेस में सहेज सकते हैं।

मज़ा!

+1

कुछ नया बनाना निश्चित रूप से एक अच्छा विचार है, लेकिन आप विवरण खतरनाक हैं। अवरुद्ध अभिनेता एक थ्रेड को अवरुद्ध करते हैं और आपका वीएम केवल इतना ही संभाल सकता है। यही है, सबकुछ लागू करना क्योंकि अभिनेता थोड़ी सी में स्केल नहीं कर सकता है। – Raphael

+0

+1 - यह निश्चित रूप से मजेदार है। मैं सहमत हूं - मुझे इस बॉक्स से बच जाना चाहिए और इसके बाहर सोचने की कोशिश करें। मुझे लगता है कि पहले चरण के रूप में मैं वास्तविक लक्ष्य पर ध्यान केंद्रित कर सकता हूं - मैं वास्तव में क्या हासिल करने की कोशिश कर रहा हूं? इस नए वास्तुकला में क्या विशेषताओं को होना चाहिए? यह ठेठ वास्तुकला का विश्लेषण करने और उन चीजों की पहचान करने में भी मददगार होगा जो मुझे इसके बारे में पसंद हैं और कुछ जो मैं सुधारना चाहता हूं। मुझे विश्वास नहीं है कि मैं अकेले अभिनेता मॉडल के साथ अपने लक्ष्यों को प्राप्त कर सकता हूं ... मैं इन सभी चीजों को सारांशित करने का प्रयास करूंगा। – tenshi

3

अभिनेताओं के साथ लेन-देन के लिए, आप अक्का की 'Transcators "है, जो एसटीएम (सॉफ्टवेयर व्यवहार स्मृति) के साथ अभिनेताओं गठबंधन पर एक नज़र रखना चाहिए: http://doc.akka.io/transactors-scala

यह बहुत कमाल की चीज़ है।

+0

मैं आपसे सहमत हूं - एसटीएम लेनदेन प्रसंस्करण के लिए अच्छा समाधान होगा जब तक कि मेरे पास कई JVM चल रहे हों। कृपया, अगर मैं गलत हूं, तो मुझे सही करें, लेकिन मुझे लगता है कि अक्का के लेनदेन में कई जेवीएम में वितरित नहीं किया जा सकता है (लेकिन जहां तक ​​मुझे पता है कि वे वितरित एसटीएम पर काम कर रहे हैं)। अगर मैं अपना ऐप स्केल करूंगा तो मैं या तो कई समान जेवीएम सेट करूँगा और उन्हें संतुलित कर दूंगा या बस अपने अभिनेताओं को कई जेवीएम में फैलाऊंगा। किसी भी मामले में मेरे सभी जेवीएम में एक ही लेनदेन नहीं हो सकता है। लेकिन डीबी लेनदेन के साथ मैं इसे प्राप्त कर सकता हूं। – tenshi

10

एसिंक्रोनस प्रोसेसिंग से बचें जब तक कि आपके पास ऐसा करने का स्पष्ट कारण न हो। अभिनेता सुंदर अवशोषण हैं, लेकिन यहां तक ​​कि वे एसिंक्रोनस प्रोसेसिंग की अंतर्निहित जटिलता को भी खत्म नहीं करते हैं।

मैंने पाया कि सत्य कठिन तरीका है।मैं संभावित अस्थिरता के एक वास्तविक बिंदु से अपने आवेदन के बड़े हिस्से को अपनाना चाहता था: डेटाबेस। बचाव के लिए अभिनेता! विशेष रूप से Akka अभिनेता। और यह बहुत अच्छा था।

हथौड़ा हाथ में, मैं फिर हर नाखून को देखने के बारे में बताता हूं। उपयोगकर्ता सत्र? हाँ, वे अभिनेता भी हो सकते हैं। उम ... उस अभिगम नियंत्रण के बारे में कैसे? जरूर, क्यों नहीं! आसानी से बढ़ती भावना के साथ, मैंने अपने अब तक एक सरल राक्षस को एक राक्षस में बदल दिया: अभिनेताओं की कई परतें, एसिंक्रोनस संदेश गुजरना, त्रुटि की स्थिति से निपटने के लिए विस्तृत तंत्र, और यूग्लीज का गंभीर मामला।

मैंने अधिकतर समर्थन किया।

मैंने उन कलाकारों को बरकरार रखा जो मुझे आवश्यक थे - मेरे दृढ़ता कोड के लिए गलती सहनशीलता - और सभी को सामान्य वर्गों में बदल दिया।

क्या मैं सुझाव दे सकता हूं कि आप सावधानी से Good use case for Akka प्रश्न/उत्तर पढ़ लें? यह आपको बेहतर समझ सकता है कि अभिनेता कब और कैसे सार्थक होंगे। क्या आपको अक्का का उपयोग करने का फैसला करना चाहिए, तो आप writing load-balanced actors के बारे में पहले के प्रश्न के उत्तर को देखना चाहेंगे।

+0

आपको अनुभव साझा करने के लिए धन्यवाद! मैं वास्तव में आपको पहले लोड संतुलन के बारे में उत्तर देता हूं और मुझे यह पसंद है - सरल और व्यावहारिक (इस बार मैं इसे वोट करने में सक्षम था :) – tenshi

3

जैसा कि आपने कहा, !! = अवरुद्धता और प्रदर्शन के लिए खराब = खराब, इसे देखें: Performance between ! and !!

लेन-देन की आवश्यकता आमतौर पर तब होती है जब आप घटनाओं के बजाय राज्य बना रहे हैं। कृपया CQRS और डीडीडीडी (वितरित डोमेन संचालित डिजाइन) और Event Sourcing पर एक नज़र डालें, क्योंकि, जैसा कि आप कहते हैं, हमें अभी भी वितरित एसटीएम नहीं मिला है।

+0

संदर्भों के लिए धन्यवाद! बहुत दिलचस्प लग रहा है, मैं निश्चित रूप से इन में खोदना होगा। – tenshi

संबंधित मुद्दे