Multithreading em Photon

Sobre o que é o artigo

Neste artigo, falaremos sobre multithreading do lado do servidor.





  • como é implementado





  • como é usado





  • o que pode ser feito





  • o que nós mesmos inventamos





Todas essas questões são relevantes apenas se você estiver desenvolvendo algo diretamente para o lado do servidor - modificando o código SDK, escrevendo seu próprio plugin ou até mesmo fazendo algo por conta própria.





Como Photon lida com multithreading?

O aplicativo do servidor de fótons aceita solicitações de várias conexões de cliente. Vou chamar tais conexões de pares . Essas solicitações formam filas. Um para cada festa. Se os pares estiverem conectados à mesma sala, suas filas serão combinadas em uma - a fila da sala. Existem até vários milhares dessas salas, e suas filas de solicitação também são processadas em paralelo.





Como base para a implementação de filas de tarefas no Photon, foi tomada a biblioteca retlang, que foi desenvolvida com base na biblioteca Jetlang.





Por que não usar Task e async / await

Portanto, existem as seguintes considerações:





  1. O fóton começou a se desenvolver antes que essas coisas aparecessem.





  2. , , - . , , , GC , . , .





  3. 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. , . :





  1. . ThreadPool.QueueUserWorkItem. - .





  2. , , 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 . :





  1. event;





  2. , , , , event ;





  3. event.





. , , , , event. . . , .





ExtendedPoolFiber ExtendedFailSafeExecutor. . , . , Pause. ( ) . :





  1. Resume





  2. ( 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.





Os executores que implementam a interface IExecutor estão diretamente envolvidos na execução de tarefas em fibras . DefaultExecutor é bom para todos, mas em caso de exceção, perde todo o restante das tarefas que lhe foram transferidas para execução. FailSafeExecutor parece ser uma escolha inteligente a esse respeito . Se você precisar realizar alguma ação antes e depois da execução de um lote de tarefas pelo executor, BeforeAfterExecutor pode ser útil








All Articles