Multithreading dans Photon

De quoi parle l'article

Dans cet article, nous parlerons du multithreading côté serveur.





  • comment est-il mis en œuvre





  • comment est utilisé





  • ce qui peut être fait





  • ce que nous avons inventé nous-mêmes





Toutes ces questions ne sont pertinentes que si vous développez quelque chose directement pour le côté serveur - modifier le code du SDK, écrire votre propre plugin ou même faire quelque chose de votre choix.





Comment Photon gère-t-il le multithreading?

L'application serveur photon accepte les demandes de plusieurs connexions client. J'appellerai de tels pairs de connexions . Ces demandes forment des files d'attente. Un pour chaque fête. Si des pairs sont connectés à la même salle, leurs files d'attente sont combinées en une seule: la file d'attente de la salle. Il existe jusqu'à plusieurs milliers de telles salles et leurs files d'attente de demandes sont également traitées en parallèle.





Comme base pour l'implémentation des files d'attente de tâches dans Photon, la bibliothèque retlang a été prise, qui a été développée sur la base de la bibliothèque Jetlang.





Pourquoi ne pas utiliser Task et async / await

Par conséquent, il y a les considérations suivantes:





  1. Photon a commencé à se développer avant que ces choses n'apparaissent.





  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.





Les exécuteurs mettant en œuvre l' interface IExecutor sont directement impliqués dans l'exécution des tâches en fibres . DefaultExecutor est bon pour tout le monde, mais en cas d'exception, il perd tout le reste des tâches qui lui ont été transférées pour exécution. FailSafeExecutor semble être un choix judicieux à cet égard . Si vous devez effectuer une action avant et après l'exécution d'un lot de tâches par l'exécuteur testamentaire, BeforeAfterExecutor peut être utile








All Articles