Tentang apa artikel itu
Pada artikel ini, kita akan berbicara tentang multithreading sisi server.
bagaimana ini diterapkan
bagaimana digunakan
apa yang bisa dilakukan
apa yang kita sendiri ciptakan
Semua pertanyaan ini hanya relevan jika Anda mengembangkan sesuatu secara langsung untuk sisi server - memodifikasi kode SDK, menulis plugin Anda sendiri, atau bahkan melakukan sesuatu sendiri.
Bagaimana Photon menangani multithreading?
Aplikasi server foton menerima permintaan dari beberapa koneksi klien. Saya akan menyebut koneksi seperti itu rekan-rekan . Permintaan ini membentuk antrian. Satu untuk setiap pesta. Jika rekan terhubung ke ruang yang sama, antrean mereka digabungkan menjadi satu - antrean ruang. Ada hingga beberapa ribu kamar seperti itu, dan antrian permintaan mereka juga diproses secara paralel.
Sebagai dasar untuk implementasi antrian tugas di Photon, perpustakaan retlang diambil, yang dikembangkan berdasarkan perpustakaan Jetlang.
Mengapa tidak menggunakan Task dan async / await
Oleh karena itu, ada beberapa pertimbangan berikut ini:
Foton mulai berkembang sebelum hal-hal ini muncul.
, , - . , , , GC , . , .
TaskScheduler, , - .
Fiber?
, . - FIFO. , multiple writers-single reader. , , , .. . .
Photon , PoolFiber, . IFiber. .
ThreadFiber - IFiber, . .
PoolFiber - IFiber, .NET. . . ( ).
FormFiber/DispatchFiber - IFiber, WinForms/WPF. FormFiber/DispatchFiber Invoke BeginInvoke .
StubFiber - . , (races) . .
PoolFiber
PoolFiber. , . :
. ThreadPool.QueueUserWorkItem. - .
, , ThreadPool.QueueUserWorkItem, . . , .
.. , , . , , () . - , , .
PoolFiber
Photon PoolFiber. , . , , . .. PoolFiber.Stop . .
. -. , , , .
:
,
, .
:
//
fiber.Enqueue(()=>{some action code;});
// , 10
var scheduledAction = fiber.Schedule(()=>{some action code;}, 10_000);
...
//
scheduledAction.Dispose()
// , 10 5
var scheduledAction = fiber.Schedule(()=>{some action code;}, 10_000, 5_000);
...
//
scheduledAction.Dispose()
, - , fiber.Schedule. .
Executors
. , . Execute(Action a)
Execute(List<Action> a)
. PoolFiber . .. . . DefaultExecutor. :
public void Execute(List<Action> toExecute)
{
foreach (var action in toExecute)
{
Execute(action);
}
}
public void Execute(Action toExecute)
{
if (_running)
{
toExecute();
}
}
. 'action' toExecute . FailSafeBatchExecutor, try/catch. , . , , github.
BeforeAfterExecutor
, . BeforeAfterExecutor. "" . , FailSafeBatchExecutor. BeforeAfterExecutor . :
public BeforeAfterExecutor(Action beforeExecute, Action afterExecute, IExecutor executor = null)
. . . / , , . , .
:
var beforeAction = ()=>
{
log4net.ThreadContext.Properties["Meta1"] = "value";
};
var afterAction = () => ThreadContext.Properties.Clear();
//
var e = new BeforeAfterExecutor(beforeAction, afterAction);
// PoolFiber
var fiber = new PoolFiber(e);
- , fiber, log4net Meta1 value.
ExtendedPoolFiber ExtendedFailSafeExecutor
, retlang, . . , . . PoolFiber ( , .NET). , , HTTP . :
event;
, , , , event ;
event.
. , , , , event. . . , .
ExtendedPoolFiber ExtendedFailSafeExecutor. . , . , Pause. ( ) . :
Resume
( Pause) Resume , , .
, , HTTP . , . Resume , .
, ThreadFiber .
IFiberAction
IFiberAction - GC. .NET. , IFiberAction. , . GC
IFiberAction :
public interface IFiberAction
{
void Execute()
void Return()
}
Execute , . Return Execute, .
:
public class PeerHandleRequestAction : IFiberAction
{
public static readonly ObjectPool<PeerHandleRequestAction> Pool = initialization;
public OperationRequest Request {get; set;}
public PhotonPeer Peer {get; set;}
public void Execute()
{
this.Peer.HandleRequest(this.Request);
}
public void Return()
{
this.Peer = null;
this.Request = null;
Pool.Return(this);
}
}
//
var action = PeerHandleRequestAction.Pool.Get();
action.Peer = peer;
action.Request = request;
peer.Fiber.Enqueue(action);
, . , . , PoolFiber . PoolFiber .NET. PoolFiber , . , ExtendedPoolFiber.
Pelaksana yang mengimplementasikan antarmuka IExecutor terlibat langsung dalam pelaksanaan tugas di fiber . DefaultExecutor baik untuk semua orang, tetapi dalam kasus pengecualian, ia kehilangan seluruh sisa tugas yang ditransfer ke sana untuk dieksekusi. FailSafeExecutor tampaknya menjadi pilihan cerdas dalam hal ini . Jika Anda perlu melakukan beberapa tindakan sebelum dan sesudah eksekusi sekumpulan tugas oleh pelaksana, BeforeAfterExecutor mungkin berguna.