Skip to content

Latest commit

 

History

History
77 lines (70 loc) · 10.4 KB

5.5Actor Location-EN.md

File metadata and controls

77 lines (70 loc) · 10.4 KB

Actor Location

Actor Location

Actor model only needs to know each other's InstanceId to send messages, which is very convenient, but sometimes we may not know each other's InstanceId, or an Actor's InstanceId will change. ET provides a mechanism to send messages to such objects, called Actor Location The mechanism is called Actor Location. The principle is relatively simple.

  1. because the InstanceId is changing, the object's Entity.Id is unchanged, so we can first think of using Entity.Id to send actor messages
  2. provide a location process (Location Server), the Actor object can store its Entity.Id and InstanceId as kv to the location process. Before sending the Actor message, go to the location process to look up the InstanceId of the Actor object before sending the actor message. 3.
  3. When an Actor object is created in a process or migrated to a new process, it needs to register its Id and InstanceId to the Location Server. 4.
  4. because the Actor object can be migrated, the message may be sent to the Actor has been migrated to other processes, so sending the Actor Location message needs to provide a reliable mechanism
  5. ActorLocationSender provides two methods, Send and Call, Send a message also requires the recipient to return a message, and only when the return message is received will the next message be sent. 6.
  6. If the Actor object is migrated away, it will return the error that the Actor does not exist, the sender will wait for 1 second after receiving this error, then go back to get the InstanceId of the Actor and resend it, currently it will try 5 times, after 5 times, it will throw an exception and report the error
  7. ActorLocationSender will not query the Location Server every time it sends a message, because object migration is relatively rare after all, only the first time to query, then cache the InstanceId, and re-query after the failure to send.
  8. actor object in the migration process, it is possible that other processes send over messages, when an error will occur, so the location server provides a Lock mechanism. Before the object is transmitted, the information in the process is deleted, and then a lock is added to the location server, and once the lock is on, other requests for the key will be queued.
  9. before transmission because the other party deleted the actor of the process, so other processes will fail to send, then they will retry. When retrying, they will re-request the location server, which will be found to be locked, so they will keep waiting.
  10. When the transmission is completed, the lock on the location server is unlocked, and the new address is updated, and then other location requests are responded to. Other requests sent to this actor continue.

Note that the Actor model is purely a server-side message communication mechanism, which has nothing to do with the client. We can use the server-side actor model for forwarding, so some client-side messages also inherit the actor interface. What happens if we don't use the actor interface on the client side? For example, the message Frame_ClickMap

message Frame_ClickMap // IActorLocationMessage
{
	int64 ActorId = 93;
	int64 Id = 94;
	
	float X = 1;
	float Y = 2;
	float Z = 3;
}

We may not need the field ActorId, the message is sent to Gate, gate sees that it is a Frame_ClickMap message, it needs to be forwarded to the Unit on the Map, forwarding is still good, gate can get the location of the unit corresponding to the map from the session, and then forward it, the problem comes, Frame_ ClickMap message to the map, how does the map know which object the message needs to be given to? There are several designs at this point.

  1. bring the Id of the unit in the underlying protocol of forwarding, which requires more complex underlying protocol support.
  2. use a message to Frame_ClickMap message wrapping, wrapping the message with the Id of the Unit, wrapping with the message means greater consumption, increasing GC. Personally, I feel that these two are very poor, not good, and even if distributed to the unit object processing, how to solve the problem of message re-entry it? unit object still needs to hang a message processing queue, and then receive the message thrown into the queue. Isn't this a duplication of the actor model? The current ET message sent to unit in the client did a design, the message into an actor message, gate received found to be an actor message, sent directly to the corresponding actor, the solution can be said to be beautiful. In fact, the client is still using session.send and call to send messages, send the message does not know that the message is an actor message, only to the gate, the gate judgment, refer to OuterMessageDispatcher.cs

Actor Location message processing

ActorLocation messages are sent

// Get the ActorLocationSenderComponent from Game.Scene, then get the ActorLocationSender via Entity.Id
ActorLocationSender actorLocationSender = Game.Scene.GetComponent<ActorLocationSenderComponent>().Get(unitId);
// Send the message through the ActorLocationSender
actorLocationSender.Send(actorLocationMessage);
// send the Rpc message
IResponse response = await actorLocationSender.Call(actorLocationRequest);

ActorLocation message processing is almost the same as Actor messages, the difference is that the two abstract classes inherited are different, note that the abstract class of actorlocation has an additional Location

	// The first generic parameter of the abstract class is the type of the Actor, and the second parameter is the type of the message.
	[ActorMessageHandler(AppType.Map)]
	public class Frame_ClickMapHandler : AMActorLocationHandler<Unit, Frame_ClickMap>
	{
		protected override ETTask Run(Unit unit, Frame_ClickMap message)
		{
			Vector3 target = new Vector3(message.X, message.Y, message.Z);
			unit.GetComponent<UnitPathComponent>().MoveTo(target).Coroutine();
			
		}
	}

	// To handle Rpc messages, you need to inherit the AMActorRpcHandler abstract class. The first generic parameter of the abstract class is the type of the Actor, the second parameter is the type of the message, and the third parameter is the type of the returned message
	[ActorMessageHandler(AppType.Map)]
	public class C2M_TestActorRequestHandler : AMActorLocationRpcHandler<Unit, C2M_TestActorRequest, M2C_TestActorResponse>
	{
		protected override async ETTask Run(Unit unit, C2M_TestActorRequest message, Action<M2C_TestActorResponse> reply)
		{
			reply(new M2C_TestActorResponse(){Info = "actor rpc response"});
			await ETTask.CompletedTask;
		}
	}

ET's actor and actor location analogy

There are many cities (processes) in China, and many people (entity objects) living in the cities, each with an ID number (Entity.Id). A person needs to apply for a residence permit in each city and is assigned a unique residence permit number (InstanceId). The format of the residence permit number is 2 bytes city number + 4 bytes time + 2 bytes increment. The ID number never changes, but the residence permit number changes every time you go to a city. Now there is a China Post (actor). Suppose Xiaoming wants to send a letter to his girlfriend Xiaohong

  1. Xiaohong must mount a mailbox (MailboxComponent) himself in order to receive the letter, and Xiaohong will process the message when he receives it. Note that processing is done here one by one. It is possible that Hong will receive letters from many people at the same time. But she must read one letter at a time. Let's say Xiaoming and Xiaobao both send letters to Xiaohong, and Xiaohong receives Xiaoming's letter first, and then Xiaobao's letter. Xiaohong reads Xiaoming's letter first, and Xiaoming's letter asks Xiaohong to make a phone call to her grandmother (to produce a concordance) and then write back to herself, noting that Xiaohong also cannot read the next letter during this period, and must finish the phone call before she can read Xiaobao's letter. Of course Xiao Hong himself can choose to start reading Xiao Bao's letter without finishing the process, by opening a new concatenation for Xiao Ming's letter.
  2. Suppose Xiaoming knows Xiaohong's residence permit number, then the post (actor) can find the city (process) where Xiaohong lives according to the two docks of the residence permit number, and then find Xiaohong and deliver the message to Xiaohong's mailbox (MailboxComponent) according to Xiaohong's residence permit number. This is the simplest native actor model
  3. ET also supports a set of actor location mechanism. Suppose Xiao Ming doesn't know Xiao Hong's residence permit number, but he knows Xiao Hong's ID number, what should he do? The postal service has developed a set of advanced post (actor location) to think of a way, if a person often moves, it still wants to receive letters, then he must report his residence permit and ID card to the central government (location server) when he goes to a new city, so that the advanced post can send mail through the ID card number. The method is to go to the central government to get Hong's residence permit number, and then use the actor mechanism to send. 4.
  4. Suppose Xiao Hong was in Guangzhou city before, and Xiao Ming used Xiao Hong's ID card to send a letter to Xiao Hong. Advanced post obtains Xiao Hong's residence permit number and sends a letter to Xiao Hong. During this process of sending the letter, Xiaohong moved, from Guangzhou to Shenzhen, at which time Xiaohong reported her new residence permit on the central government. When the letter from the senior post arrives in Guangzhou, it is found that Xiao Hong is not in Guangzhou. Then the senior postal service will go to the central government again to get Xiao Hong's residence permit and resend it, which may succeed or fail again, this process will be repeated several times, if it is unsuccessful, it will tell Xiao Ming that the letter has failed to be sent.
  5. senior postal mail is more expensive, and people do not move a lot, usually Xiao Ming will remember Xiao Hong's residence permit after sending letters with senior postal mail, and next time send letters directly with the residence permit, and then send letters with senior postal mail if it fails. There are two kinds of return receipts, one without content, just means Xiao Hong received the letter, and one with Xiao Hong's return letter. Xiaoming can choose which return receipt form to use when he sends the letter. Xiao Ming cannot send two letters to Xiao Hong at the same time, he must wait for Xiao Hong's acknowledgement to arrive before Xiao Ming can continue sending the letter.