为什么80%的码农都做不了架构师?>>>
一个应用系统,分布有中心与区节点个环节,系统间由于中心与节点处理内外网关系,系统中要进行双向的通信需NAT穿透,简单选型使用了Soket通信,由节点主动上连中心,提供服务,并保存套接字。
Netty是一个事件驱动,多线程的,支持多种协议与支持NIO的一个JAVA编写的Socket框架,使用Netty可以省去了很多开发中遇到的问题。
系统应用架构上根据了DDD做为参考,领域层-中心的Server , 节点的Client, 定义为了两个聚合根,行为类型,动作起来需要组合不同的聚合跟实例进行相关业务逻辑操作。
应用服务一层位于领域层之上,用于负责领域事件注册,事务控制的一个Facade层。
项目中有这样的一个场景:
中心Server通过一定机制,发送信令到对应的节点Client,节点Client接收到的信令进行相关操作(操作数据库,WebService请求),这些操作都均耗时耗资源,我们第一直观感觉是使用多线程解决,从而不阻塞Netty的相应InboundHandler在管道中进行下一个节点进行操作,项目中也确实是这样用了。:^)
对于这个相关操作,关系到了数据库事务控制等这些问题,而节点在Client位于领域层,按照DDD的思路,这一类的操作应该交由应用服务的某个方法执行。但接入到信令的操作发生在领域层,而领域层并不能获取到上层应用服务接口,这促使了我在项目中选用了领域事件,进行事件发布。
由应用服务层注册事件Subscriber,进行订阅,获取到领域事件后,交由同一层(应用服务)的服务接口进行操作。解决了不同层次依赖问题。
大致的思路,用些精简的伪代码表示:
准备领域事件的几个类
DomainEventPublisher事件发布器
public class DomainEventPublisher
{
public void publish(DomainEvent event,ExecutorService execotor)
{
...
executor.execute(new Runnable(){
public void run()
{
for(DomainEventSubscribe subscribe : this.subscribes)
{
subscribe.handle(event);
}
}
);
}
public void subscribe(DomainEventSubscribe subscribe){...}
}
DomainEvent 领域事件接口
public interface DomainEvent{}
DomainEventSubscriber 事件订阅者接口
public interface DomainEventSubscribe
{
void handle(DomainEvent domainEvent);
}
定义领域层Client端
Client聚合根
public class Clent
{
private DomainEventPublisher publiser;
public void open()
{
// ...netty的api等
//加入一个自定义的handler
channel.pipeline().addLast( new AppHandler() );
}
public void close(){...}
public void subscribe(DomainEventSubscribe subscribe)
{
this.publiser.subscribe(subscribe);
}
}
AppHandler
public class AppHandler extends ChannelInboundHandler
{
private DomainEventPublisher publisher;
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
Signalling signalling = (Singalling) msg;
String data = signalling.data();
AppDomainEvent event = new AppDomainEvent(data);
publisher.publish(event,ctx.channel().eventLoop());
...
}
}
AppDomainEvent,我们实现的领域事件
public class AppDomainEvent implements DoaminEvent
{
public AppDomainEvent(String data){this.data = data}
public String data(){return data}
}
应用层
ClientApplicationService,创建Client的一些Facade接口
public class ClientApplicationService
{
public void newClient(String clientId)
{
Client client = new Client(clientId);
client.subscribe( new AppDomainEventSubscriber() );
return client;
}
}
AppDoaminEventSubscriber订阅器
public class AppDomainEventSubscriber implements DomainEventSubscribe
{
public void handle(DomainEvent event)
{
if(event.class.equals( AppDomainEvent.class ) )
{
AppDoaminEvent e = (AppDomainEvent) event;
ApplicationRegister.otherApplicationService().do(e.data());
}
}
}
注:ApplicationRegister.otherApplicationService()的意思是获取改领域层的其他应用服务,来进行对领域事件中带回来的data进行业务操作。
以上便是偶在项目中的一个解决方案,希望有帮助。