Akka2使用探索1(Remoting)

akka從1.2升級到如今的2.0.2後有了很大的改變。如今摸索一下如何使用。服務器

 

Remoting能夠方便地用於服務器之間通訊。akka1.2可使用clientActor.sendRequestReply將消息發送到服務器端,而且同步獲取服務器端的返回消息。可是akka2已經不能這麼用了,akka2使用tell方法給另外一個Actor發消息。網絡

tell有兩個重載方法:app

/**
* Sends the specified message to the sender, i.e. fire-and-forget semantics.<p/>
* <pre>
* actor.tell(message);
* </pre>
*/
final def tell(msg: Any): Unit = this.!(msg)(null: ActorRef)ide

只發送,無論其餘,也不接收相應。actor.tell(msg)----給actor發送msg消息this

 

/**
* Java API. <p/>
* Sends the specified message to the sender, i.e. fire-and-forget
* semantics, including the sender reference if possible (not supported on
* all senders).<p/>
* <pre>
* actor.tell(message, context);
* </pre>
*/
final def tell(msg: Any, sender: ActorRef): Unit = this.!(msg)(sender)
url

只發送消息,並告訴對方你能夠給我指定的sender回覆消息。actor.tell(msg,sender)----給actor發送msg消息,actor處理時能夠給sender回覆消息。
spa

因此akka2中actor是對等的。有消息來回發送的akka應用最好部署在對等互通的網絡環境中。若是一個應用部署在內網,一個部署在外網,那麼內網的actor給外網發消息沒問題,可是外網的actor想給內網的actor回覆消息就不行了。.net

 

另外,由於remoting的host最好指定成具體的ip或域名或hostname,不要指定成」0.0.0.0」,這樣才方便定位遠程actor。host和port在配置文件中指定。debug

注意區別Deploy,Deploy是指將本地Actor發佈到遠程akka Server上,withDeploy的參數RemoteScope指的是遠程Server的ip、端口、sysName。並非啓動本地Server。netty

serverActor = system.actorOf(new Props(Server.class).withDeploy(new Deploy(new RemoteScope(new Address("akka", Server.AkkaSystemName, "127.0.0.1", 8888);))), "simple");

客戶端能夠直接用serverActor發消息,也能夠經過路徑查找,用actorFor(akka://${遠程sysName}@${遠程akka服務地址}/remote/${被髮布的sysName}@${被髮布的akka的地址(ip、端口)}/user/${actorOf第二個參數指定的路徑})發消息。注意消息是在服務端收到。

 

如今來看看具體的例子:

 

首先引用typesafe的倉庫:

<repository>
    <id>typesafe-releases</id>
    <url>http://repo.typesafe.com/typesafe/releases</url>
</repository>

 

加入依賴包:<akka.version>2.0.2</akka.version>

<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-actor</artifactId>
    <version>${akka.version}</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-remote</artifactId>
    <version>${akka.version}</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-kernel</artifactId>
    <version>${akka.version}</version>
</dependency>

 

首先定義ServerActor:

import akka.remote.RemoteScope
import akka.actor.*
import com.typesafe.config.ConfigFactory
class Server extends UntypedActor {
    static final String AkkaSystemName = "xw"
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);

    @Override
    void onReceive(Object message) {
        log.debug("server收到消息----${message}----self:${getSelf()},sender:${getSender()}")
        getSender().tell(message)//給客戶端actor發送消息
    }

}

而後定義服務端應用,來啓動ServerActor

import akka.kernel.Bootable
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.ActorRef
import akka.actor.Address
import akka.actor.Deploy
import akka.remote.RemoteScope
import com.typesafe.config.ConfigFactory

class ServerApp implements Bootable {
    ActorSystem system
    ActorRef serverActor   

    ServerApp() {
        system = ActorSystem.create(Server.AkkaSystemName, ConfigFactory.load().getConfig("server"))
        Address addr = new Address("akka", Server.AkkaSystemName, "10.68.15.16", 8888);
        serverActor = system.actorOf(new Props(Server.class), "server");

//        serverActor = system.actorOf(new Props(Server.class).withDeploy(new Deploy(new RemoteScope(addr))), "simple");
    }

    void startup() {

    }

    void shutdown() {
        system.shutdown()
    }

}
指定它加載「server」配置。須要在classpath下的application.conf中添加:

server {
    akka {
        //loglevel = "DEBUG"
        actor {

            provider = "akka.remote.RemoteActorRefProvider"//這裏指定使用RemoteActor

        }
        remote {
            transport = "akka.remote.netty.NettyRemoteTransport"
            netty {
                hostname = "10.68.15.16"//"0.0.0.0"//指定系統綁定的host
                port = 8888//指定系統綁定的端口
            }
        }
    }
}
如今只須要new ServerApp()將服務啓動便可。

 

客戶端很簡單:

ActorSystem.create(Server.AkkaSystemName, ConfigFactory.load().getConfig("client")).actorFor("akka://xw@10.68.15.16:8888/user/server").tell("hello,I'm client")

客戶端也須要加載配置文件:

client {
    akka {

        actor {
            provider = "akka.remote.RemoteActorRefProvider"

        }

    }
}

這裏須要注意:

一、必須指定provider爲RemoteActorXXX

二、客戶端只發不收消息時,ActorSystem的name沒有要求。須要收消息時,若是和服務端相同則可能出問題。遇到問題時改下ActorSystem的那麼試一下。

 

通過試驗,若是服務端啓多個ActorSystem和akka端口是沒問題的。akka1.2中同一個進程不能啓多個akka端口。

相關文章
相關標籤/搜索