Agent service and overload protection

In the SkyNet, it is necessary to implement a pre-active agent service for a service.

For example, you want the request to be initiated to this service to support timeout, you don’t have to implement in the service-implemented service, which will increase the unnecessary complexity. You can add a proxy service before the service implemented, when the timeout occurs, the requester will be notified. With regard to this implementation, I have given an example in Blog.

Similarly, when you need to do some load balancing, you can also be a proxy service, allowing the request to share to multiple services that can complete similar functions, and the implementation is relatively simple. This article is not expanded.

Today I want to talk about how to use the agent to provide overload protection for some hot service services.

Overload protection I wrote two years ago, the two years of operational product experience suggested that it is the most easily encountered question for lack of experience Skynet users. This may also be a problem that the environment is most needed.

I think about the future version and do some more underlying protection measures. However, current SkyNet 1.0 version, we can still do some work on the upper level.

Suppose we already know that a service is easy to become a hotspot, then a front agency service can do a lot of things.

The so-called proxy service is to initiate a request to the real functional service, requiring the message to another proxy service, forwarding this request to the real functional service; Similarly, the response message will be forwarded by the proxy service.

When you filter these messages, you can do some work, for example:

If a service request is too frequent, you can put these requests for the time being, and the request for other services can be forwarded. This increases the fairness. And if the service of the request source has exited, if there is still a request he has not issued in the proxy service, you can discard these messages and reduce the burden on functional services.

We can also use the load conditions of the functional service to survey the service survey, and if the function service is too busy, you can temporarily caching new requests. This allows us to respond faster when we initiate commissioning control commands to the functional service from the debug console. (From the debugging console to initiate commands, without agents), when the problem is solved online, after overload, the debug instruction response is extremely reduced to reduce the efficiency of the fault on the line.


Skynet has provided a good support for writing agency services, you can refer to the ClusterProxy service to write your own service agent.

Usually a proxy service is like this:

local skynet require “skynet” require “skynet.manager” – inject skynet.forward_typeskynet.register_protocol {name “system”, id skynet.PTYPE_SYSTEM, unpack function (…) return … end,} local forward_map {[skynet .PTYPE_LUA] skynet.PTYPE_SYSTEM, [skynet.PTYPE_RESPONSE] skynet.PTYPE_RESPONSE, – do not free response message} local realsvr tonumber ((…)) skynet.forward_type (forward_map, function () skynet.dispatch ( “system “, Function (Sension, Source, MSG, SZ) SkyNet.ret (SkyNet.Rawcall (RealsVR,” Lua “, MSG, SZ) End) End)

The above code is incomplete, you need to make it according to your real business logic.

Use SkyNet.Forward_Type to provide a mapping table, indicating which types of protocols you need to do. In addition, the usage of Skynet.Start is consistent.

In the protocol message in the mapping table, the framework does not release the memory occupied by the message, which is to avoid unnecessary messages; at the same time, you must carefully handle them, avoid memory leakage.

In the above example, all LUA protocol categories are redirected to the System category (so you can redefine the UNPACK function, do not make any unpacking process). Then in the subsequent DISPATCH function, use SkyNet.Rawcall to send a message pointer directly to bypass the packaging process and the unpacking process of the response package.

The Response class message is also mapped here, just to let the frame do not release it. In subsequent Dispatch, the response package returned by SkyNet.rawCall is a C pointer and length, and it can be replied to the original request party directly to SKYNET.RET. The example here only processes messages that request response mode. If you also forward the unidirectional skynet.send behavior, you can judge whether the session is zero. (The session of the request message is not equal to 0 integers)

How to determine if the functional service is overloaded?


If you are online monitoring, you can view the log. At present, when the message queue is too long, “May Overload, Message Queue Length XXX” will be output.

Service you can also check the length of the message queue to be processed by SkyNet.mqlen.

If you want to take the query that the other party may process the message in time, a relatively simple method is to implement an agreement and return immediately. As a request, use SkyNet.now to test the response speed of this request. In the latest SKYNET version, I added the default Debug protocol ping to do this.

Local Ti SkyNet.now () Skynet.call (Address, “Debug”, “Ping”) TI skynet.now () – TI

With Debug Console, you can use the ping address command.

BTW. Using Debug Ping in the above agent service is safe. Although the behavior of the Response class message is modified by Skynet.Forward_Type to not release, the debug ping protocol is special, and the content of its response message is empty.

If you need to initiate other requests in the proxy service, remember to use RawCall and destroy the response package pointer.

Skynet.trash (Skynet.Rawcall (Address, “Lua”, Skynet.Pack (…)))

Need manually destroying the ping of the Response message.

How to get a service instant to exit?


Skynet recommends the practice is to use SkyNet.monitor to define a self-monitoring service. All services have notified it. But this usage is now not recommended.

If the monitored service is a Lua service, the simplest method is to send a request that never returns to this service. When the service exits normally, the request that is not returned will throw an error from the framework to the request party. So, as long as you use PCALL to initiate a SkyNet.call to the service that needs to be monitored, you can perceive the service exit.

Skynet latest version adds a debug directive Link to help you do this:

PCall (SkyNet.call, Address, “Debug”, “LINK”)