Use summary of actor framework-protoactor based on Go

Source: Internet
Author: User
Tags eventbus
This is a creation in Article, where the information may have evolved or changed. > A year is fleeting, November 16 because of business needs, began to build the actor tool Library, because cluster under the grain implementation is too difficult, April 17 to switch to the Protoactor with this feature, to now, use this framework for almost a year. All the way to trample the pit countless, while these days planning the next stage of business, on the time to chat. # # # Protoactor framework of the basic points of the *actor* framework is basically similar to the CSP in the same age, compared to the latter, the Actor in the past 10 years to a little fire, after all, the current emphasis on rapid development, most developers pay more attention to business implementation, which conforms to the * The actor* focuses on the object that receives the message (*csp* more emphasis on the transport channel). The design and implementation of Protoactor, most of which are similar to *akka*, are only slightly different in serialization, service discovery and registration, and in several parts of the life cycle. The framework uses the same overall as the *akka*, but is limited by the go language, which is a bit different in terms of usage details. * * Message passing ***protoactor* through *mpsc* (multi produce single consumer) structure to achieve system-level message delivery, through the Ringbuffer to achieve business messaging, by default can buffer 10 business messages. Cross-service delivery, each of the Services node even RPC client, is also the service side of RPC. The node sends a message in the RPC request package to receive a possible message reply with the RPC service. * * Based on gprc** 's RPC package relative to the Go standard library, GRPC has more advantages, including but not limited to: 1. Not in support of the traditional response mode, but also support the invocation of three kinds of stream, simplifying the design of large data flow API. Therefore, when there is a large amount of data between the nodes, there is no need to worry about the business, even if the number of megabytes of data, GRPC will flow control, according to the default 64K packet delivery (if you feel small, can be set artificially). 2. Based on HTTP/2, direct support for TLS in today's increasingly popular cloud services, transmission encryption is a very important requirement, which greatly simplifies security development inputs. * * Serialization ***protoactor* the PROTOBUF3 serialization protocol adopted by default for cross-service data defines the encapsulation of cross-service messages and does not support other protocols such as Msgpack, thrift, and so on. * * Service Registration **protoactor Each node allows service registration through consul, but the name under cluster must be the same. At present, small problems are more, for the time being not recommended for production environment "behind will explain why." # # # Protoactor Use experience *protoactor* can be considered to be the most earlyMature Asynchronous Queue Package framework, basically can achieve most of the business, shielding the underlying RPC, serialization of the specific implementation. * * Shield The PIT * * Although a big highlight of Go is goroutinue, but many of the pits, on a very simple code in the client normal, on-line ' play.golang.org ' absolutely run: ' ' gofunc main () {var ok = true// As of go1.9.2, if the server is only 1CPU, it cannot be dispatched. Go func () {time. Sleep (time. Second) OK = False} () for OK {}fmt. PRINTLN ("program run end! ")}" in the framework, through the "atomic" and other biased interface, basically did not use Goroutinue and Chan, the implementation of the asynchronous queue message delivery and function calls, and through the ' runtime. Goschedule ' avoids the problem of other tasks waiting in the event of a busy business. Therefore, many times, it as an asynchronous message queue to improve service wayward, is a good choice, do not have to write the CSP every time. * * in actor. Started message response Completion initialization * * Although we write the implementation of the ' Actor ' interface, this implementation code (called Myactor) does not initialize the business data externally. Involves a database read, provides at most one UID, and then receives the ' *actor. Starting ' message is processed. For example, define: "' Gotype myactor struct{uid stringmycontext myactorcontext//Business context structure definition//...} Func (My *myactor) Receive (CTX actor. Context) {switch msg:=ctx. Message (). (type) {Case *actor. Started://Perform data loading, initialize Mycontext//respond to other events}} ' to do this, there are three benefits: 1. Actor creation is usually performed by ' system ' or ' parent actor ', which is a relatively time-consuming type of IO operation like database loading, which can cause it to block. 2. Loading business many times there are startup, crash replies, which are called in both cases, which are part of the actor lifecycle and are more consistent in encapsulation. 3. The load operation overrides the local variable and executes the ' Props ' action, emphasizing that the template is immutable, while the UID of the myactor is constant. * * Prohibit the use of the ' frominstance ' * * Official example file, usingA lot of ' frominstance ' to build the actor, because the go language is not an object-oriented language, the method is actually repeated using the same instance, after the business exception crash recovery, the instance is not reset. We will find that some of the previous variables have not been reset (' frominstance ' may be abolished later) * * Message categorization with Duck interface * Initially, our business is a node. Later, the node's business needs to be split into "front-end access" and "several backend different scene services", because the message definition does not support advanced features such as inheritance, the use of the same name to increase the definition of the property, and provide default values: "' Protobufmessage request{ Required Int64 Router = 1[default 10];optional Int64 UserId = 2;} The > client can only use PROTOBUF2, which is exactly the default feature. Since the ' Request ' code generated by PROTOBUF is sure to generate ' getrouter ', we can define such an interface to categorize messages with the same properties: ' Gotype Router interface{func getrouter () Int64} "In this way, we can easily forward the front-end message to the corresponding backend server without enumerating all the messages and not using the ' reflect ' package. > Similarly, Scala's case object is compiled with the product interface implementation, and as long as the property order is the same, you can cast the attribute in the corresponding ordinal to classify it. Kotlin temporarily did not see a similar feature. # #ProtoActor的坑在使用过程中, enjoy the convenience of the framework, but there are many unexpected problems. Compared to Akka, is not mature enough, after submitting feedback usually a week will have a reply, about half of the repair, the others are #¥#@%#. More serious, there are probably a few points: * * State switching has no practical significance **actor very stressed state, in different states to deal with business logic is very convenient for business grooming. *protoactor* defines only one method for the ' actor ' interface: ' go//actor is the interface, that defines the receive method.////receive is sent message s to being processed from the mailbox associated with the instance of the Actortype Actor INTERFACe {receive (c Context)//<-only This method implementation} ' can use ' setbehavior ' to change the message receiving function, so as to achieve the purpose of state switching. But the system message does not have the same as *akka*, directly to the ' Postrestart ', ' poststop ', ' Prestart ' these three methods. Thus, regardless of the state of the business actor, the message received by the system must be processed in the message receiving function, which results in a very bloated message reception function: "Gofunc (actor *myactor) Receive1 (CTX actor). Context) {handlesystemmsg (ctx. Message)//...} Func (actor *myactor) Receive2 (CTX actor. Context) {actor.handlesystemmsg (ctx. Message)//<-typically each State responds to system messages, avoiding business crashes that result in data not being saved, etc./...} Response System Message func (actor *myactor) handlesystemmsg (msg interface{}) {switch msg. (type) {case *actor. Started:case *actor. Stopping:case *actor. Restart:case *actor. Restarting:}} ' causes the state to switch to a different message entry and has to write again to receive the system message, which results in the Setbehavior ' (*akka* called ' become ') loss of practical meaning. * * Life cycle slightly different * * The life cycle of the framework is slightly different from the Akka, under normal circumstances: started->stopping->stopped. Where stopping is executed before the actor is stopped, and stopped is written off after the actor. This is to be very careful that if stopping crashes, the actor object will not be freed. If a crash occurs during a business run, the framework sends a message recovery: restarting->started. This process is very different from the Akka recovery process (stopped->restarted). * * Do not cross the watch** familiar with Akka developers are more clear that the child actor is allowed to be created across processes, across service nodes. But the framework of the remote package in the design of insufficient, once the node fails, even if the recovery, the two nodes are alsoThe connection could not be established, resulting in an unacceptable message. And the framework originally emphasized that ' grain ' must be in cluster mode, based on ' watch ', ' unwatch ', so it can't be used properly. This problem was initially discovered in remote mode because: * * cannot be monitored * * The asynchronous framework, if not monitored, is equivalent to an airplane blind drop, problem diagnosis can be very difficult. Protoactor message passing between different actors is achieved by defining ' Messageenvelop ', and three properties have a very important role: The envelope type of the message is passed between "Go//actor" Messageenvelope struct {header messageheader///business extends information outside the head, typically used for statistics, monitoring, more in interceptors using message interface{}//Specific de business message sender *pid//message sender, But the sender calls the Tell method, and the sender is empty} "' However, there is no solution to the header in the interceptor after the use of the default global header information. The request code is as follows: "' Gofunc (ctx *localcontext) Request (PID *pid, Message interface{}) {env: = &messageenvelope{header: Nil,//<--If the actor accepts the previous message, there is no way to pass the header, which is reset to Nilmessage:message,sender:ctx. Self (),}ctx.sendusermessage (PID, ENV)} "it is obvious that when the actor sends a message to another actor, the header is reset to ' nil ' and the same is true of the ' tell ' method. After communication on GitHub, it is said to be considering performance. It would be nice to add a function ' Forward ' that could pass the header: ' Gofunc (CTX *localcontext) Forward (PID *pid, Message interface{}) {env: = & Messageenvelope{header:ctx. Header,//<--assumes that this method can get the header information of the current CTX, and if nil, gets the global headermessage:message,sender:ctx. Self (),}ctx.sendusermessAge (PID, ENV)} "In addition, the initial header is not defined at different nodes (or different processes), but this attribute is added at the end of 17, which means that the header information can be intercepted when the first actor receives the message. * * No native schedule**actor timing state is usually provided using timed messages, although go native timer is very useful, but the cost is not small, and when the actor exits, it is impossible to revoke the reference. Usually, however, the actor size is not large, and its implementation is relatively straightforward. * * Messages without a native eventbus** framework do not provide categorization, subject delivery, and only one ' EventStream ' provides all actor broadcasts. In the attempt to copy Akka's ' Eventbus ' is indeed complex, found that the go language implementation is really very complex, eventually give up. # #总结尽管很多年前因为折腾 *protoactor*, I understand how asynchronous queues * and *actor* are implemented, but none of them are so large-scale in code size. After applying the actor in depth, it has to be said that there is a huge difference with CSP. In contrast, the scenarios are very different:-*csp* concern queue, lower level, lighter, simple asynchronous processing-*actor* focus on instance state, heavy, default in the instance with a shell (Pid+context,akka is Actorref+context), Encapsulates two queues (MSPC, Ringbuffer) three collections (children, Watchers, watchees) to handle complex business logic. Objectively speaking, Protoactor's Open source creator considers or is very full, in the serialization method, the message format is determined, has constructed the go, C #, Kotlin (This is a demo demo), different nodes can be implemented in these languages. The source code is also worth learning (it is recommended to use an IDE that tracks the interface definition and implementation code). From the update, C # faster (don't understand why not Microsoft Official Orlean), the go language side is more follow the version of C # iteration, there seems to be no voice. Overall, *protoactor* still have a lot to improve spending, but for the whole day also because the business of ' Mutex ' brought deadlock, need to find a way out, may wish to try a different kind of thinking. Over the past year, although the ability to use ' Mutex ' has declined sharply, the business implementation of Windows observation and battle synchronization is much quicker and ^_^. [Original link: protoactor use summary] (http://blog.csdn.net/qq_26981997/article/details/79138111) 398 reads  
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.