Skip to content
/ koala Public

Koala is a cross-platform framework for building distributed applications with python asyncio.

License

Notifications You must be signed in to change notification settings

egmkang/koala

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Koala是一个跨平台, 用于构建可扩展的分布式有状态服务框架

Koala是一个异构的服务器框架, 其中网关用C#编写, PlacementDriver服务器使用Golang编写, Framework主体使用Python.

Koala采用了asyncio, 将async/await语法引入到整个framework以及编程模型上. 可以帮助任何熟悉async/await协程的人, 轻松的写出可以横向扩展的, 高性能有状态服务.

Koala在Python Asyncio之上实现了Virtual Actor模式, 该模式由微软研究院开发出来, 最早使用在Orleans项目上. 所以Koala本身拥有很多Orleans的优点, 实现上略有不同.

Actors

Koala Framework的核心是Actor. 一个Actor就是Interface + Identity + State. Interface定义了该Actor所能提供的能力, Identity则用于同类Actor之间做隔离. 同时Koala还提供了持久化状态存储的帮助类库, 可以满足不同粒度的持久化. 一个Actor可以实现一个或者多个Interface, 可以在内存中存储或者不存储状态, Koala在这方面提供了较强的组合能力.

Koala Framework大量使用Python TypeHints, Actor之间的通讯是强类型的RPC, 可以(在动态语言上)提供友好的编程体验.

Actor的生命周期由Runtime控制, 用户不需要手动控制Actor的资源释放. Koala提供了额外的控制Actor生命长短, Actor加载和卸载的接口, 方便用户做额外的控制. 一般来讲用户不需要关心Actor是否存在, 只需要通过Interface直接调用Actor; 用户也不需要关心Actor在哪个服务器上, PD会找一个负载相对较轻的服务器来放置Actor实例, 同时Placement的维持强一致性.

FastAPI

Koala Framework通过集成FastAPI来提供HTTP API, 可以无缝的和其他系统集成. 同时FastAPI可以访问Actor系统, 来实现有状态服务.

FastAPI也使用asyncio和TypeHints, 可以提供比较一致的编程体验.

Actor例子

有一个IPlayer接口, 有一个echo函数.

class IPlayer(ActorInterface):
    @abstractmethod
    async def echo(self, hello: str) -> str:
        pass

然后PlayerImpl类实现了IPlayer接口, 这就是IPlayer对象真正执行的逻辑.

class PlayerImpl(IPlayer, ActorBase):
    def __init__(self):
        super(PlayerImpl, self).__init__()

    async def echo(self, hello: str) -> str:
        return hello

这时候就可以去拿到IPlayer的proxy对象, 去异步的执行RPC.

# 1
proxy = get_rpc_proxy(IPlayer, "1")
echo_response = await proxy.echo("111222")
print(echo_response)    # 这里就会打印111222

# 2
class XXXActor(XXXInterface, ActorBase):
    ...
    async def func(self):
        proxy = self.get_proxy(IPlayer, "2")
        echo_response = await proxy.echo("222111")        
        ...

例1里面, 就可以在一个外部系统直接去调用Koala Actor; 例2则是在Actor与Actor之间调用, Koala和Orleans一样实现了RPC的可重入, 这在Koala里面是默认实现而且不能关闭的(Orleans里面有开关).

HTTP例子

用HTTP API来实现一个Echo, 其中Http只是提供接口, Actor用来响应真正的请求.

# Actor接口
class IPlayer(ActorInterface):
    @abstractmethod
    async def echo(self, msg: str) -> str:
        pass
    pass

# HTTP接口
@app.get("/")
def root():
    return "hello world"


@app.get("/echo/{msg}")
async def echo(msg: str):
    proxy = get_rpc_proxy(IPlayer, "1")
    result = await proxy.echo(msg)
    return result

例子中, echo请求都会发送给IPlayer/1这个对象, 实际操作中, 可以选择合适的ID分布, 以满足更高的并发度和分摊服务器压力.

Koala Runtime

Koala Runtime使用Python3 AsyncIO编写, 可以在Windows/Linux/macOS上面方便的调试和运行.

由于Actor之间已经做了隔离, Host进程这时就可以理解为一个容器, 里面放着不同类型不同ID的Actor实例. Koala Framework处理了Actor的位置算法, 以及Actor之间的通讯, 以及检测和故障恢复. 所以用户在调试单进程Host的时候可以正常工作, 就可以方便将程序扩展到整个集群.

除此之外, Koala Runtime还提供WebSocket, 协议无关的网关. 用户只需要实现首包规范, 后续就可以在WebSocket上传输自定义协议, 而不需要关心网关的实现. 后续网关还会支持QUIC协议, 用来提供更低延迟的交互服务.

特点

分布式有状态

Actor作为可编程的最小粒度, 可以将状态存储在Actor内部. 对外只表现出来Interface + Identity, 对内则表现出来实现细节和State. 实现细节上甚至可以在有状态服务内实现一个无状态的Actor, 有非常大的灵活性.

持久化

Koala提供了Actor Storage的抽象, 提供了最多两列的存储接口, 即(Key1, Optional<Key2>) => Object. 用户可以像Orleans那样将整个State存储到一个对象里面, 这样只需要使用Key1即可; 也可以将整个State分割成多个存储对象, 将一个存储对象分割成多行, 可以自由的组合. 在某些领域, 单个State的尺寸可能会比较大, 只提供整个对象的读写性能可能会比较低, 所以Koala在这方面只是做一个可选的Storage抽象, 并没有在Actor内做成强制性的.

Actor Timer

Koala没有提供Orleans的reminder, 但是提供编程必须的Timer. Actor的消息派发会执行Timer, 所以Timer和RPC一样也是顺序执行的, 同时Timer会进行补偿, 不会发生明显的时间偏移和误差累积.

强一致的Placement

Koala在设计之初就考虑了如何实现一个强一致性的Placement, 虽然整个Koala不是一个CP系统, 但是还是在这方面做了一些努力. KoalaPlacementDriver服务器使用golang编写, 集成了etcd embed, 集群Membership和服务发现依赖etcd, 这方面的强一致的; Placement依赖于etcd的分布式锁和额外的持久化缓存. 整个集群内的Membership和Placement信息会不一致(会最终一致), 但是当服务不可用的时候Koala不会选择立即切换可能有故障的服务, 而是等待etcd续约失败, 同时在目标服务器上面也会二次检测Placement的正确性.

Fault Tolerance

Koala设计之初就考虑了可扩展性. 当一个新的机器加入到集群内, 集群会迅速感知到新节点的存在, 然后会尝试着将新的任务调度给新的节点; 当一个节点离开集群(或是出现故障), 集群也会感知到, 然后将那个节点上的Actor移动到其他可用节点上重新激活. 集群会自动检测服务的存活性, 并且自动恢复故障.

异构系统

Koala Framework主体使用Python语言, Gateway使用C#, PlacementDriver使用golang. 虽然使用了3种语言, 但是服务器与服务器之间的通讯经过了设计, 可以跨语言和进程. 甚至可以对某个进程进行重新实现, 都是可以的, 只需要满足Protocol即可, 详情可以参考doc中对Protocol细节的描述.

跨平台

Koala Framework整体都可以在Windows/Linux/macOS上面Debug运行. 用户可以方便的将集群运行在托管虚拟机, Docker, 或者物理机上.

License

本项目采用MIT许可证.

链接