akka mysql_Spray + Akka高性能异步IO并发

Spray + Akka高性能异步IO并发

如何使用Java建立像Node.js那样非堵塞异步事件并发IO服务器呢?Spray是基于NIO2高并发框架,虽然Tomcat 8也是基于NIO2,但是Spary的线程数要低得到,降低CPU上下文切换的负载;Akka和其Mysql库包都是相同线程执行上下文( execution context),因为在非堵塞前提下,性能拼的就不是线程数目越多越好,正好相反,线程数目越低,越接近理论理论最佳点。

启动设置

为了启动Spary和Akka,需要一个main启动函数,在main函数中,我们创建一个Actor系统:

ActorSystem system=ActorSystem.create("system");

ActorRef listener=system.actorOf(Props.create(HttpActor.class),"httpActor");

listener是使用Actor用来处理Http请求。然后要设定监听Http的端口:

InetSocketAddress endpoint=newInetSocketAddress(3000);

intbacklog=100;

Listoptions=JavaConversions.asScalaBuffer(newArrayList()).toList();

Optionsettings=scala.Option.empty();

最后,绑定Actor到监听的Http端口:

Bind bind=newHttp.Bind(listener, endpoint, backlog, options, settings, sslEngineProvider);

IO.apply(spray.can.Http$.MODULE$, system).tell(bind, ActorRef.noSender());

整个main函数主要代码如下:

publicstaticfinalActorSystem system=ActorSystem.create("system");

publicstaticvoidmain(String[] args) {

...

ActorRef listener=system.actorOf(Props.create(HttpActor.class),"httpActor");

InetSocketAddress endpoint=newInetSocketAddress(3000);

intbacklog=100;

Listoptions=JavaConversions.asScalaBuffer(newArrayList()).toList();

Optionsettings=scala.Option.empty();

ServerSSLEngineProvider sslEngineProvider=null;

Bind bind=newHttp.Bind(listener, endpoint, backlog, options, settings, sslEngineProvider);

IO.apply(spray.can.Http$.MODULE$, system).tell(bind, ActorRef.noSender());

...

}

设置好启动函数以后,下面是真正开始在Actor里处理进来Http请求了。

请求处理器

首先,我们因为使用的是原生Java代码,不是Scala,因此需要将Scala集成到Java中,可能比较丑陋,可以用专门类包装一下,引入Scala的Http协议:

HttpProtocolHTTP_1_1=HttpProtocols.HTTP$div1$u002E1();

Http Actor为了响应Http请求做三件事,第一件是创建一个路由router,这样能够根据请求URL:http://xxx/path中不同的/path分别处理:

Router router=partitionAndCreateRouter();

第二件是处理新的连接,告诉Spray这个actor不仅接受Http连接,也处理实际http连接:

}).match(Tcp.Connected.class, r->{

sender().tell(newHttp.Register(self(), Http.EmptyFastPath$.MODULE$), self());//tell that connection will be handled here!

})

第三件事就是处理实际的Http连接,将http请求委托给另外一个actor处理。

.match(HttpRequest.class, r->{

intid=Constants.ID.getAndIncrement();

String path=String.valueOf(r.uri().path());

if("/sell".equals(path)){

...//逻辑处理

}elseif("/buy".equals(path)){

...//逻辑处理

}else{

handleUnexpected(r);

}

})

整个HttpActor代码如下,业务逻辑以买卖为模型:

privatestaticclassHttpActorextendsAbstractActor{

privatestaticfinalHttpProtocolHTTP_1_1=HttpProtocols.HTTP$div1$u002E1();

publicHttpActor() {

finalRouter router=partitionAndCreateRouter();

receive(ReceiveBuilder

.match(HttpRequest.class, r->{

intid=Constants.ID.getAndIncrement();

String path=String.valueOf(r.uri().path());

if("/sell".equals(path)){

String productId=r.uri().query().get("productId").get();

...

SalesOrder so=newSalesOrder(price, productId, quantity, id);

so.setSeller(newSeller(who));

router.route(so, self());

replyOK(id);

}elseif("/buy".equals(path)){

...

}else{

handleUnexpected(r);

}

}).match(Tcp.Connected.class, r->{

sender().tell(newHttp.Register(self(), Http.EmptyFastPath$.MODULE$), self());//tell that connection will be handled here!

}).build());

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值