Akka.net路径里的user

因为经常买双色球,嫌每次对彩票号麻烦,于是休息的时候做了个双色球兑奖的小程序,做完了发现业务还挺复杂的,于是改DDD重做设计,拆分服务,各种折腾...,不过这和本随笔没多大关系,等差不多了再总结一下,有空就写出来。

上面说了拆服务,拆成了录入,开奖,兑奖三个服务,三个服务开始是用消息队列的,不过后来发现其实就是服务的领域对象之间的交互,就联想到了Actor,面向对象于是一切都是对象,actor也是一切都是actor,看着就门当户对,于是就干掉消息队列。。。细节以后有机会再说。

上面其实也和这随笔没啥关系,有关系的是,因为时间关系,没去了解akka的文档,于是好奇一件事,服务器连接地址中的"user"是哪来的:

//var section = (AkkaConfigurationSection)ConfigurationManager.GetSection("akka");

//using (var system = ActorSystem.Create("TestClient", section.AkkaConfig))

            using (var system = ActorSystem.Create("TestClient"))
            {
                var actor = system.ActorSelection("akka.tcp://[email protected]:8081/user/tester");

                while (true)
                {
                    var input = Console.ReadLine();
                    if (input.Equals("1"))
                    {
                        actor.Tell(new DTO("11111"));
                    }
                    else if (input.Equals("2"))
                    {
                        actor.Tell(new DTO("22222"));
                    }
                    else
                    {
                        actor.Tell(new DTO("H W"));
                    }
                }
            }

上面是客户端,下面是服务端:

 1             var config = ConfigurationFactory.ParseString(@"
 2             akka {
 3                 actor {
 4                     provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
 5                 }
 6                 remote {
 7                     helios.tcp {
 8                         transport-class = ""Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote""
 9                         applied-adapters = []
10                         transport-protocol = tcp
11                         port = 8081
12                         hostname = localhost
13                     }
14                 }
15             }
16             ");
17
18             using (var system = ActorSystem.Create("TestServer", config))
19             {
20                 system.ActorOf<TestDTOActor>("tester");
21
22                 Console.ReadLine();
23             }

文档想必很多,最近有别的要看,于是想想看看代码得了,反正一时还不会用到生产环境,到时候再说吧,先解决好奇的问题。

于是首先是ActorSystem的实现类ActorSystemImpl,system.ActorOf<TestDTOActor>("tester")对服务端路径影响的应该是ActorOf:

        public override IActorRef SystemActorOf<TActor>(string name = null)
        {
            return _provider.SystemGuardian.Cell.ActorOf<TActor>(name);
        }

于是找找_provider:

        public ActorSystemImpl(string name, Config config)
        {
            if(!Regex.Match(name, "^[a-zA-Z0-9][a-zA-Z0-9-]*$").Success)
                throw new ArgumentException(
                    "invalid ActorSystem name [" + name +
                    "], must contain only word characters (i.e. [a-zA-Z0-9] plus non-leading ‘-‘)");
            if(config == null)
                throw new ArgumentNullException("config");

            _name = name;
            ConfigureSettings(config);
            ConfigureEventStream();
            ConfigureProvider();
            ConfigureTerminationCallbacks();
            ConfigureScheduler();
            ConfigureSerialization();
            ConfigureMailboxes();
            ConfigureDispatchers();
            ConfigureActorProducerPipeline();
        }

        private void ConfigureSettings(Config config)
        {
            _settings = new Settings(this, config);
        }

        private void ConfigureProvider()
        {
            Type providerType = Type.GetType(_settings.ProviderClass);
            global::System.Diagnostics.Debug.Assert(providerType != null, "providerType != null");
            var provider = (IActorRefProvider)Activator.CreateInstance(providerType, _name, _settings, _eventStream);
            _provider = provider;
        }
        public Settings(ActorSystem system, Config config)
        {
            _userConfig = config;
            _fallbackConfig = ConfigurationFactory.Default();
            RebuildConfig();

            System = system;

            ConfigVersion = Config.GetString("akka.version");
            ProviderClass = Config.GetString("akka.actor.provider");
            var providerType = Type.GetType(ProviderClass);
            if (providerType == null)
                throw new ConfigurationException(string.Format("‘akka.actor.provider‘ is not a valid type name : ‘{0}‘", ProviderClass));
            if (!typeof(IActorRefProvider).IsAssignableFrom(providerType))
                throw new ConfigurationException(string.Format("‘akka.actor.provider‘ is not a valid actor ref provider: ‘{0}‘", ProviderClass));

            SupervisorStrategyClass = Config.GetString("akka.actor.guardian-supervisor-strategy");

            AskTimeout = Config.GetTimeSpan("akka.actor.ask-timeout", allowInfinite: true);
            CreationTimeout = Config.GetTimeSpan("akka.actor.creation-timeout");
            UnstartedPushTimeout = Config.GetTimeSpan("akka.actor.unstarted-push-timeout");

            SerializeAllMessages = Config.GetBoolean("akka.actor.serialize-messages");
            SerializeAllCreators = Config.GetBoolean("akka.actor.serialize-creators");

            LogLevel = Config.GetString("akka.loglevel");
            StdoutLogLevel = Config.GetString("akka.stdout-loglevel");
            Loggers = Config.GetStringList("akka.loggers");

            LoggerStartTimeout = Config.GetTimeSpan("akka.logger-startup-timeout");

            //handled
            LogConfigOnStart = Config.GetBoolean("akka.log-config-on-start");
            LogDeadLetters = 0;
            switch (Config.GetString("akka.log-dead-letters"))
            {
                case "on":
                case "true":
                    LogDeadLetters = int.MaxValue;
                    break;
                case "off":
                case "false":
                    LogDeadLetters = 0;
                    break;
                default:
                    LogDeadLetters = Config.GetInt("akka.log-dead-letters");
                    break;
            }
            LogDeadLettersDuringShutdown = Config.GetBoolean("akka.log-dead-letters-during-shutdown");
            AddLoggingReceive = Config.GetBoolean("akka.actor.debug.receive");
            DebugAutoReceive = Config.GetBoolean("akka.actor.debug.autoreceive");
            DebugLifecycle = Config.GetBoolean("akka.actor.debug.lifecycle");
            FsmDebugEvent = Config.GetBoolean("akka.actor.debug.fsm");
            DebugEventStream = Config.GetBoolean("akka.actor.debug.event-stream");
            DebugUnhandledMessage = Config.GetBoolean("akka.actor.debug.unhandled");
            DebugRouterMisconfiguration = Config.GetBoolean("akka.actor.debug.router-misconfiguration");
            Home = Config.GetString("akka.home") ?? "";
            DefaultVirtualNodesFactor = Config.GetInt("akka.actor.deployment.default.virtual-nodes-factor");

            SchedulerClass = Config.GetString("akka.scheduler.implementation");
            //TODO: dunno.. we dont have FiniteStateMachines, dont know what the rest is
            /*
                final val SchedulerClass: String = getString("akka.scheduler.implementation")
                final val Daemonicity: Boolean = getBoolean("akka.daemonic")
                final val DefaultVirtualNodesFactor: Int = getInt("akka.actor.deployment.default.virtual-nodes-factor")
             */
        }

很明显,看配置文件的akka.actor.provider:

<configuration>
  <configSections>
    <section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
  </configSections>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <akka>
    <hocon>
      <![CDATA[
          akka {
                actor {
                    provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
                }
                remote {
                    helios.tcp {
                        transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
                        applied-adapters = []
                        transport-protocol = tcp
                        port = 0
                        hostname = localhost
                    }
                }
            }
      ]]>
    </hocon>
  </akka>
</configuration>

于是RemoteActorRefProvider:

        public LocalActorRef SystemGuardian { get { return _local.SystemGuardian; } }

        public RemoteActorRefProvider(string systemName, Settings settings, EventStream eventStream)
        {
            settings.InjectTopLevelFallback(RemoteConfigFactory.Default());

            var remoteDeployer = new RemoteDeployer(settings);
            Func<ActorPath, IInternalActorRef> deadLettersFactory = path => new RemoteDeadLetterActorRef(this, path, eventStream);
            _local = new LocalActorRefProvider(systemName, settings, eventStream, remoteDeployer, deadLettersFactory);
            RemoteSettings = new RemoteSettings(settings.Config);
            Deployer = remoteDeployer;
            _log = _local.Log;
        }

好吧,看LocalActorRefProvider:

        public void Init(ActorSystemImpl system)
        {
            _system = system;
            //The following are the lazy val statements in Akka
            var defaultDispatcher = system.Dispatchers.DefaultGlobalDispatcher;
            _defaultMailbox = () => new ConcurrentQueueMailbox(); //TODO:system.Mailboxes.FromConfig(Mailboxes.DefaultMailboxId)
            _rootGuardian = CreateRootGuardian(system);
            _tempContainer = new VirtualPathContainer(system.Provider, _tempNode, _rootGuardian, _log);
            _rootGuardian.SetTempContainer(_tempContainer);
            _userGuardian = CreateUserGuardian(_rootGuardian, "user");
            _systemGuardian = CreateSystemGuardian(_rootGuardian, "system", _userGuardian);
            //End of lazy val

            _rootGuardian.Start();
            // chain death watchers so that killing guardian stops the application
            _systemGuardian.Tell(new Watch(_userGuardian, _systemGuardian));    //Should be SendSystemMessage
            _rootGuardian.Tell(new Watch(_systemGuardian, _rootGuardian));      //Should be SendSystemMessage
            _eventStream.StartDefaultLoggers(_system);
        }
        private LocalActorRef CreateUserGuardian(LocalActorRef rootGuardian, string name)   //Corresponds to Akka‘s: override lazy val guardian: LocalActorRef
        {
            return CreateRootGuardianChild(rootGuardian, name, () =>
            {
                var props = Props.Create<GuardianActor>(UserGuardianSupervisorStrategy);

                var userGuardian = new LocalActorRef(_system, props, DefaultDispatcher, _defaultMailbox, rootGuardian, RootPath/name);
                return userGuardian;
            });
        }

看样子,这个RootPath还重载了操作符:

        public static ActorPath operator /(ActorPath path, string name)
        {
            return new ChildActorPath(path, name, 0);
        }

        public static ActorPath operator /(ActorPath path, IEnumerable<string> name)
        {
            var a = path;
            foreach (string element in name)
            {
                a = a / element;
            }
            return a;
        }

现在_userGuardian路径是看到了,生拼上去的,那么哪里用的呢

LocalActorRefProvider:

     public LocalActorRef Guardian { get { return _userGuardian; } }

RemoteActorRefProvider:

     public LocalActorRef Guardian { get { return _local.Guardian; } }

再回来看system.ActorOf<TestDTOActor>("tester")这句:

        public override IActorRef ActorOf(Props props, string name = null)
        {
            return _provider.Guardian.Cell.ActorOf(props, name: name);
        }

这就是我自己配的provider造成的,其实还是配置问题,当然,这么看我们其实可以实现自己的provider,想怎么搞就怎么搞,有时间其实还是应该看下文档,不过想来文档应该会说怎么用什么样,当应该不会说怎么实现的,要知道为什么,怎么改,估计还是要自己看代码,此致。

时间: 2025-01-17 15:22:28

Akka.net路径里的user的相关文章

Xcode中怎么引用Source Trees定义路径里的头文件

做的项目中需要引用Source Trees定义路径里的头文件,刚开始没有头绪,稍加思索发现太简单了. 此Source Trees非彼Source Tree,是Xcode"偏好设置"中的一个选项,见下图: 以上面的"QUICK_COCOS2DX_ROOT"一项为例,我遇到的问题是想在工程中引用这个路径下include文件夹里的头文件. 一般情况下如果想把某个文件夹中的头文件加入到工程中,可以在Build Setting中的Hearder Search Path里添加形

文件路径里的短路径

win7 x64环境下 有2个IE文件夹 C:\PROGRA~1\INTERN~1\iexplore.exe  这样调用的是x64的浏览器 C:\PROGRA~2\INTERN~1\iexplore.exe  这样才是调用的是Program Files (x86)下的浏览器

获取路径里的参数

//获取参数值function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return decodeURI(r[2]); return null;}

Java Web项目里 classpath 具体指哪个路径

classpath路径指什么 只知道把配置文件如:mybatis.xml.spring-web.xml.applicationContext.xml等放到src目录(就是存放代码.java文件的目录),然后使用"classpath:xxx.xml"来读取,都放到src目录准没错,那么到底classpath到底指的什么位置呢? WEB-INF/classes目录存放src目录java文件编译之后的.class文件,xml.properties等资源配置文件,这是一个定位资源的入口. sr

AKKA文档(java版)

目前我正在翻译AKKA官网文档.翻译:吴京润 译者注:本人正在翻译AKKA官网文档,本篇是文档第一章,欢迎有兴趣的同学加入一起翻译.更多内容请读这里:https://tower.im/projects/ac49db18a6a24ae4b340a5fa22d930dc/lists/ded96c34f7ce4a6bb8b5473f596e1008/show/https://tower.im/projects/ac49db18a6a24ae4b340a5fa22d930dc/todos/640e53d

路径层函数

路径层函数CBrush::CreateSolidBrushBOOL CreateSolidBrush( COLORREF crColor );返回值 成功非零; 失败返零.参数 crColor 是颜色结构体变量,指定画刷颜色. 颜色可以是指定一个RGB值,也可以通过WINDOWS.H的RGB宏来构造说明:用指定的固体颜色初始化画刷:可以被任何设备上下文选为当前画刷.应用完由CreateSolidBrush创建的画刷要将它从设备上下文里取出. CDC::FillPathBOOL FillPath(

Python搜索路径

转自:http://www.jbxue.com/article/15324.html 在python编程中,模块的导入需要一个叫做"路径搜索"的过程.即在文件系统"预定义区域"中查找 mymodule.py文件(如果你导入 mymodule 的话).这些预定义区域只不过是你的 Python 搜索路径的集合. 默认搜索路径是在编译或是安装时指定的.它可以在一个或两个地方修改.一个是启动 Python 的 shell 或命令行的 PYTHONPATH 环境变量. 该变量

QT里使用sqlite的问题,好多坑

1. 我使用sqlite,开发机上好好的,测试机上却不行.后来发现是缺少驱动(Driver not loaded Driver not loaded),代码检查了又检查,发现应该是缺少dll文件(系统不提示,是自己使用 QMessageBox::warning(NULL, ("error"), database.lastError().text());后猜到的).于是自己千方百计的想办法,反复测试,就是不行.结果悲剧的发现,原来是多次设置路径错误,浪费一上午时间.应该直接在可执行exe

spring mvc修改配置文件路径

1.1.  Classpath 工程目录 在web.xml文件如下配置: <!-- 配置spring mvc 的核心servlet --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <