转载

Orbit框架解析

Orbit是在JVM上的一个使用虚拟actor来做分布式系统的框架。它使得开发者在开发分布式和易扩展的应用的时候,能够极大简化系统的集群、服务发现、网络、状态管理、actor生命周期等特性的开发。

Orbit是由EA(对,就是那个著名游戏公司)的下属游戏子公司Bioware(开发了无冬之夜、质量效应等优秀游戏)开发并开源的,这个框架的灵感是由微软的Orleans框架得来的,其目前的版本是1.1.0,这个版本优化了本地缓存,其使用了caffeine cache,增强了KryoSerializer,并优化了一些性能。Orbit所需的环境是java8、maven3.1及以上。Orbit这个框架目前在github上有超过一千的star,不算太小众,而且还获得了2016年的Duke's Choice Award for Open Source,所以还是值得一看的。

Orbit的一个重要组件是actor,actor之间的通信都是通过异步消息来交互的,Orbit确保一个actor不会同时被并行调用,这样开发者就不用担心actor的并发访问问题,但是如果开发者使用@Reentrant这个annotation来标识actor的话,当服务被阻塞时就能够让另一个请求进来(其实还是只有一个线程在活动)。创建一个actor时必须得先创建一个接口,如下,这个interface必须extends Orbit的Actor接口,然后里面定义的方法的返回类型必须是Orbit的Task类。Task类对CompletableFuture进行了简单的封装,可见Actor的方法都是通过异步回调方式来处理的。

public interface Chat extends Actor  
{

    @OneWay
    Task<Void> say(ChatMessageDto message);

    Task<Boolean> join(ChatObserver observer);

    Task<Boolean> leave(ChatObserver observer);

    Task<List<ChatMessageDto>> getHistory(int messageCount);
}

然后你得创建一个类来实现上述接口,如下,这个类得extends Orbit的AbstractActor抽象类,并且这个类一次只能实现一个actor的接口。

public class ChatActor extends AbstractActor<ChatActor.State> implements Chat  
{
    private int maxMessages = 1000;

    private long lastSave;

    public static class State
    {
        ObserverManager<ChatObserver> observers = new ObserverManager<>();
        LinkedList<ChatMessageDto> history = new LinkedList<>();
    }

    @Override
    public Task<Void> say(final ChatMessageDto message)
    {
        System.out.println(message.getMessage());
        if (getLogger().isDebugEnabled())
        {
            getLogger().debug("Message received: " + message.getMessage());
        }
        message.setWhen(new Date());
        state().history.add(message);
        trimHistory();
        state().observers.notifyObservers(o -> o.receiveMessage(message));
        if (System.currentTimeMillis() - lastSave > TimeUnit.SECONDS.toMillis(60))
        {
            return writeState();
        }
        return Task.done();
}
省略。。。
}

不像别的框架,在Orbit中没有明确的actor的生命周期管理,actor不会创建和销毁,在概念上它是一直存在的。只不过它是分为“活动”和“不活动”两种状态,如果一个actor 被加载到内存中,那就是“活动”的,如果没有那就是相反。

Stage是Orbit的另一个重要组件,它是一个运行时执行容器,并且它是开发者与actor交互的重要手段。Orbit默认会使用UDP广播模式结合JGroups、Infinispan组件来做集群间的通信,但是通常UDP广播模式不太适合做云部署(比如AWS就没有提供UDP广播的支持),所以Orbit可以让开发者来配置具体的通信方式(如tcp通信),可以自定义xml配置文件放置到资源路径classpath下,如:classpath:/conf/jgroups.xml。

Actor能通过定义一个内部静态类来保存自己的状态,如下,可见还需要在extends AbstractActor的时候定义一下泛型。

public class StatefulActor extends AbstractActor<StatefulActor.State> implements Some  
{
    public static class State
    {
        String lastMessage;
    }
}

这个状态操作起来也很方便,在actor的创建时就已经生成了它的内部静态类的一个实例,然后通过state()这个方法来获取这个实例,然后操作里面的属性。并且还能通过writeState()、readState()等方法来持久化存取状态(需要有相应的存储扩展)。

通常情况下Orbit只允许同id的actor只有一个是“活动”中的,不过有些情况下actor是无状态的,并且想提高吞吐量和降低响应时间,那就可以使用@StatelessWorker这个annotation,这样就能支持同id的actor能有多个实例“活动”着了。

Orbit有良好的扩展机制,目前官方也提供了很多不错的扩展,比如AWS S3、MongoDB、Jetty、HK2等的支持,自己去实现一些扩展也是很容易的,Orbit提供了很多扩展接口出来,如关于存储方面的StorageExtension,S3、MongoDB的扩展实现了这个接口,关于生命周期的LifetimeExtension,HK2的扩展实现了这个接口。

Orbit还与spring有了简单的集成,帮助开发者通过配置文件配置相关参数来自动创建stage并维护在容器里。还提供了OrbitHealthIndicator这个HealthIndicator(需要引入spring boot actuator)来监控容器内stage的状态,通过actuator暴露的rest api来获取信息。

目前Orbit还比较年轻,不过已经开始用于Bioware公司里的一些项目里,让我们多关注关注这些新兴的框架,说不定哪天它们就能火呢,哈哈。

原文  http://tech.dianwoda.com/2017/06/30/orbitkuang-jia-jie-xi/
正文到此结束
Loading...