[关闭]
@yangyc 2018-03-08T12:53:24.000000Z 字数 3843 阅读 704

微服务

functional_3d_engine_pattern


https://martinfowler.com/articles/microservices.html#DecentralizedDataManagement
https://www.jianshu.com/p/39c1e4ec0d63

service->logic, data 分离

multi layer service

面向数据来切分服务

各个service相互独立,只操作自己的数据

each service logic should not duplicate

提出问题,给出答案

结合案例,采用迭代的方式来展现模式的演化,展示是如何一步步完善模式的!

服务契约:
http://geek.csdn.net/news/detail/231684 -> 消费者驱动契约模式

为了解决各个service之间需要相互调用的情况(如gameObject包含了component,因此gameObject服务需要对应操作component服务), 提出个模块(取名为Combiner?Linker?Connector?ServiceMesh?)(叫aggr service比较好,因为该模块就是负责组合多个service为一个大的service)来负责组合多个service的通用逻辑,但不属于service,应该属于service调用者所在的模块
调用者可依赖该模块,也可以直接调用service(相当于utils)
(e.g. GameObject->处理component的data的逻辑放在这里,而GameObject jobService只负责处理gameObjectData)

aggr service在新的层!和single service不在同一层!

////传入整个state到该模块?
把需要的各个service data传入?

为了解决“调用者不需要知道state中各个service data存在”的问题,提出api facade层,即:
调用者->api facade->service

把该逻辑放到api facade中(参考编辑器)

如果调用者调用api facade,会降低一些性能(
可能会增加拼装state的次数

api facade类似于 微服务中的API Gateway :

https://www.cnblogs.com/savorboard/p/api-gateway.html

aggr service(聚合服务) 参考:

https://www.cnblogs.com/savorboard/p/api-gateway.html -> 聚合服务

http://geek.csdn.net/news/detail/231684 -> 微服务的分解和组合模式

之所以引擎job直接使用service,而不使用api的原因:
1.这样性能更好
减少了组合state、从state中获得data的次数

之所以编辑器直接使用api,而不使用service的原因:
1.编辑器不关注性能

2.编辑器直接操作engine state,不操作engine state中的record

为了解决service中重复代码,以及通用程度不同的问题,采用service分层:
可以往下跨层调用service
(这样子可以减少不必要的桥接代码)
(桥接是没有必要的,因为:
如果需要增加逻辑,则可以变为一个新的服务(操作同一个data的新的服务)
)
aggr service作为最上层service
(
all service module name should be XxxService.re instead of XxxAggrService.re, XxxCommonService
)

粗粒度层的服务可以互相调用
(操作state,record的service可以,操作单个数据的common/base service不行)

/*
什么逻辑放到下一层service中(如common service)?
1.本层service中重复使用的逻辑
2.操作更小的数据
(e.g.
camera->dirtyArray逻辑
)

如果函数是操作更小数据,但不是重复逻辑,则可作为私有函数
*/

如何判断service在哪层?
根据操作的数据粒度来判断
如:
操作多个state的service在一层
->
操作一个state或者一个state中多个数据的service在一层
->
操作state中某个数据的service在一层

(
操作一个state并不意味者函数形参只有这一个数据,只是说函数只会改变这一个state。

"操作state中某个数据"同理
)

聚合服务
本质上是因为数据之间有依赖关系,所以需要聚合服务。
e.g.
engine state中的gameObjectRecord 与 basicMaterialRecord之间有依赖关系,因此对应这两个record的service也有依赖关系,因此需要GameObject聚合服务(如dispose gameObject)
(需要进一步说明!)

将数据分层:
按照 数据 粒度 来分层

tuple(state tuple) -> state -> record -> primitive -> atom

service的分层与数据分层一一对应

在不同的层,service的名字的抽象程度也不一样:
e.g.
在record层,GameObjectContainerXXXService
在state层,DisposeGameObjectService

与ECS, job的关系:
1.从数据的角度来看
service是从数据的角度来看,将数据分成多层
ECS是站在record层的抽象
job是站在record及以上层
(需要进一步分析!!!)

关于API facade:
编辑器的API facade其实是tuple层的服务!

compare with:
component(ecs)
layer(editor)

好处:
案例->editor:
使用前:
view,buss层与ui组件一一对应(与 功能?需求? 耦合)
区分了editor和engine(edit, oper, adapter)

使用后:
view,buss对应到api facade
edit, oper, adapter对应到service

推广(移到三级模式->job + microservice?):
增加新的引擎(e.g. 物理引擎), 有什么影响?
并行开发(job+api+service)
////每个引擎提供自己的(aggr service, )
不影响其它引擎开发
新引擎->共享/依赖其它引擎的service

针对此问题的解决方法:
////开发新引擎时,除了增加自己的service,其它依赖的service保持不变(就算他们更新了,也保持不变)
其它引擎的service的修改需要随时通知新引擎(持续集成)
(可以把新引擎与其它引擎都放在同一个project下)
(
或者新引擎为一个project A,其它引擎的service为一个project B;
A每天持续更新依赖的B的npm包
)

集成到主引擎中时成本很小:
只影响"新引擎->共享/依赖其它引擎的service"这部分

测试代码如何写?
直接调用api facade,不调用service

测试的tool:
只需要API facade tool(不需要service tool)

每个测试文件(针对功能feature区分)的重复代码放到哪?:
////也微服务化?
////还是说保留 每个测试文件/功能 tool
(
对于editor:
测试分成:
1.ui component tool
////2.api facade tool
2. service tool

对于engine:
测试分成:
////1.api facade tool
1. service tool
)

新思想:
函数即服务
(
每个函数就是一个独立的服务,而不是每个.re文件(module)!
)

优缺点
可参考 https://www.cnblogs.com/imyalost/p/6792724.html -> 八、优点和缺点

好处:
service互不影响

显示定义定义了service api,明确了服务的概念:
Another consequence of using services as components is a more explicit component interface. Most languages do not have a good mechanism for defining an explicit Published Interface. Often it's only documentation and discipline that prevents clients breaking a component's encapsulation, leading to overly-tight coupling between components. Services make it easier to avoid this by using explicit remote call mechanisms.

数据相互独立(不再依赖整个state)

这些好处都要结合案例来说明!

缺点:
Moving code is difficult across service boundaries, any interface changes need to be coordinated between participants, layers of backwards compatibility need to be added, and testing is made more complicated.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注