zoukankan      html  css  js  c++  java
  • Elixir游戏服设计三

    玩家进程用gen_server来建模,我不直接使用 use GenServer, 而是使用exactor,该库可以去掉反锁的接口定义。

    我们新建一个 player_server_manager app吧, 使用 mix new player_server_manager --sup, 会给我们增加sup。然后在mix.exs里增加exactor的依赖如下:

      defp deps do
        [{:exactor, "~> 2.2"}]
      end

    跑 mix deps.get,成功了依赖就准备好了。

    默认生成的player_server_manager.ex

    defmodule PlayerServerManager do
      use Application
    
      # See http://elixir-lang.org/docs/stable/elixir/Application.html
      # for more information on OTP Applications
      def start(_type, _args) do
        import Supervisor.Spec, warn: false
    
        children = [
          # Define workers and child supervisors to be supervised
          # worker(PlayerServerManager.Worker, [arg1, arg2, arg3]),
        ]
    
        # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
        # for other strategies and supported options
        opts = [strategy: :one_for_one, name: PlayerServerManager.Supervisor]
        Supervisor.start_link(children, opts)
      end
    end

    玩家进程就叫player_server吧。把它改成我需要的。

    defmodule PlayerServerManager do
      use Application
    
      # See http://elixir-lang.org/docs/stable/elixir/Application.html
      # for more information on OTP Applications
      def start(_type, _args) do
        import Supervisor.Spec, warn: false
    
        children = [
          # Define workers and child supervisors to be supervised
          worker(PlayerServer, [], restart: :temporary),
        ]
    
        # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
        # for other strategies and supported options
        opts = [strategy: :simple_one_for_one, name: PlayerServerManager.Supervisor]
        Supervisor.start_link(children, opts)
      end
    end

    因为玩家进程是动态创建的,因此采用simple_one_for_one, 同时我不需要默认传参数,还有我不需要重启。

    好了现在让我们编写PlayerServer模块(现在是简单的,而且我还未知有什么需要调整的,后续随着服务器设计而演化吧)。

    让我们先增加个查询钻石的接口吧。

    defmodule PlayerServer do
    
        use ExActor.GenServer
    
        defstart start_link(player), do: initial_state(%{player: player, socket: nil})
        defcall gem, state: state, do: reply(state.player.base_info.gem)
    end

    我们在PlayerServerManager里增加启动接口如下

     def start_player_server(%Player{} = player) do
        Supervisor.start_child(PlayerServerManager.Supervisor, [player])
      end

    在player_server_manager_test.exs里增加测试代码

    defmodule PlayerServerManagerTest do
      use ExUnit.Case
      doctest PlayerServerManager
      
      setup do
        Application.stop(:player_server_manager)
        :ok = Application.start(:player_server_manager)
      end
    
      setup do
          player = Player.new(0)
          {:ok, player: player}
      end
      test "start player_server", %{player: player} do
        assert {:ok, pid} = PlayerServerManager.start_player_server(player)
        assert  PlayerServer.gem(pid) == 0
      end
    end

    测试通过。

    写到这里发现之前Player和BaseInfo @behavior 实际上应该为@hehaviour, 既然之前没报错,我就把它去掉了,测试依然通过。说明其实可能只需要

    defdelegate。

    好了,这一章就到这。遗留的问题有,我们通常需要给玩家进程一个名字,而不是通过pid,如果是单节点的话, local 注册已经足够,如果是跨服访问,我们需要一个分布式的注册机制(实际上分布式注册机制容易有坑,如无必要,千万别)。比如gporc,比如syn。 前者比较有名,我以前在erlang用过,之前有碰到莫名奇妙的问题。所以下章试试syn吧。

  • 相关阅读:
    Root Android and Install Recovery linux shell script & Android root原理
    MPEG4 144962和H.264什么区别?
    Android root的两种方法 udev漏洞和setuid漏洞
    [转载]android三个特殊的资源目录 /res/xml /res/raw 和 /assets
    avast注册号|好用的avast注册号|没过期avast注册号
    忘记烦恼|如何忘记烦恼|忘记烦恼的方法
    第六感|最近又出现第六感了这个是什么问题呢
    移动手机为什么还有话费,就停机了,和客服的谈话
    .net保存中文到cookie时是乱码取出来的时候
    skype账号|超值skype账号|14分钟skype账号|1元40个|15天有效期
  • 原文地址:https://www.cnblogs.com/rubyist/p/5535624.html
Copyright © 2011-2022 走看看