sofastack/sofa-registry

对Model抽象的疑惑(Publisher、UnPublisher、Subscriber、Watcher)

Opened this issue · 9 comments

dbl-x commented

Your question

Publisher、UnPublisher、Subscriber、Watcher这四个类的定义都在model..common.model.store中,所以他们都是存储相关的模型吗?但是他们中又带有业务逻辑,比如:
image
如果他们是业务模型,但它们似乎又都用户数据传输相关的操作。

另外UnPublisher作为一个模型对象本身是不合适的吧?

Your scenes

存储模型(类DTO对象不应当包好业务逻辑),业务模型应当和存储模型进行分离

Your advice

对存储模型、业务模型做好清晰的抽象

Environment

  • SOFARegistry version: 6.1.9
  • JVM version (e.g. java -version):
  • OS version (e.g. uname -a):
  • Maven version:
  • IDE version:

最早是V5的时候,有watcher、publisher和subscriber等概念,作为几种不同类型的客户端,存储在不同的“Store”里面,这么设计也是最初V5使用了多个线程池,通过task对象进行解耦,所以,将元信息封装在“model”对象中。

而V6我们改版时候,经过压测等手段,发现异步解耦有如下问题:

  1. 实战下来,过度地一步解耦导致对象之间的关系不明确,很容易混淆,加之没有单测,很容易出现问题
  2. 性能大坑,无法很好处理IO类任务和计算类任务,以及优先级问题

后来,针对异步队列进行了解耦,但是留下了原有的对象,存储。

再后来,对象本身好像被加了一些定义,这个 @bjxiaojian 比较清楚

  • Subscriber作为一个对象,我理解是可以有包含对象自身特性的一些方法的,比如截图中的Subscriber对象是否被推送过,我理解这个不属于具体的业务逻辑;
dbl-x commented

最早是V5的时候,有watcher、publisher和subscriber等概念,作为几种不同类型的客户端,存储在不同的“Store”里面,这么设计也是最初V5使用了多个线程池,通过task对象进行解耦,所以,将元信息封装在“model”对象中。

而V6我们改版时候,经过压测等手段,发现异步解耦有如下问题:

  1. 实战下来,过度地一步解耦导致对象之间的关系不明确,很容易混淆,加之没有单测,很容易出现问题
  2. 性能大坑,无法很好处理IO类任务和计算类任务,以及优先级问题

后来,针对异步队列进行了解耦,但是留下了原有的对象,存储。

再后来,对象本身好像被加了一些定义,这个 @bjxiaojian 比较清楚

  1. 如果缺少单测应该补充单测,我觉得这个不是问题
  2. 不知道这一点的性能的坑具体只什么,是对象转换带来的申请内存的开销吗?
dbl-x commented
  • Subscriber作为一个对象,我理解是可以有包含对象自身特性的一些方法的,比如截图中的Subscriber对象是否被推送过,我理解这个不属于具体的业务逻辑;

如果这个对象是common.model.store下的,我建议是不要带有”业务逻辑“。

结合一下DataStore#add方法,Publisher、UnPublisher、Subscriber、Watcher都是能被add到DataStore里面的,以及他们实现了Serializable接口,所以他们应该是数据模型。就像你要像DB插入一行数据,你插入的肯定是数据,而不是数据结构。

最早是V5的时候,有watcher、publisher和subscriber等概念,作为几种不同类型的客户端,存储在不同的“Store”里面,这么设计也是最初V5使用了多个线程池,通过task对象进行解耦,所以,将元信息封装在“model”对象中。
而V6我们改版时候,经过压测等手段,发现异步解耦有如下问题:

  1. 实战下来,过度地一步解耦导致对象之间的关系不明确,很容易混淆,加之没有单测,很容易出现问题
  2. 性能大坑,无法很好处理IO类任务和计算类任务,以及优先级问题

后来,针对异步队列进行了解耦,但是留下了原有的对象,存储。
再后来,对象本身好像被加了一些定义,这个 @bjxiaojian 比较清楚

  1. 如果缺少单测应该补充单测,我觉得这个不是问题
  2. 不知道这一点的性能的坑具体只什么,是对象转换带来的申请内存的开销吗?

性能的坑具体只什么:这个就是一些很直接的调用,改为要先入队到线程池里面,然后,由线程池执行任务时,触发消费方的执行。无形地让一个纯内存的操作,变成了上下文切换 + 阻塞队列 的操作。性能损耗就在这里。

线程池解耦比较适合一些重IO操作的异步化,内存操作还是同步比较好,放线程池不但不解决问题,还会导致性能损耗。

背景就是这么的。

dbl-x commented

最早是V5的时候,有watcher、publisher和subscriber等概念,作为几种不同类型的客户端,存储在不同的“Store”里面,这么设计也是最初V5使用了多个线程池,通过task对象进行解耦,所以,将元信息封装在“model”对象中。
而V6我们改版时候,经过压测等手段,发现异步解耦有如下问题:

  1. 实战下来,过度地一步解耦导致对象之间的关系不明确,很容易混淆,加之没有单测,很容易出现问题
  2. 性能大坑,无法很好处理IO类任务和计算类任务,以及优先级问题

后来,针对异步队列进行了解耦,但是留下了原有的对象,存储。
再后来,对象本身好像被加了一些定义,这个 @bjxiaojian 比较清楚

  1. 如果缺少单测应该补充单测,我觉得这个不是问题
  2. 不知道这一点的性能的坑具体只什么,是对象转换带来的申请内存的开销吗?

性能的坑具体只什么:这个就是一些很直接的调用,改为要先入队到线程池里面,然后,由线程池执行任务时,触发消费方的执行。无形地让一个纯内存的操作,变成了上下文切换 + 阻塞队列 的操作。性能损耗就在这里。

线程池解耦比较适合一些重IO操作的异步化,内存操作还是同步比较好,放线程池不但不解决问题,还会导致性能损耗。

背景就是这么的。

嗯 理解,不过这个应该跟这里的模型抽象没有太多的关系。模型并不会一定要绑定在异步的模式上。

dbl-x commented

Publisher、UnPublisher、Subscriber、Watcher,其中UnPublisher甚至不是一个名词

Publisher、UnPublisher、Subscriber、Watcher 这几个是data和session上存储的具体业务对象,UnPublisher 是 UnRegister这个动作生产的一个对象。
对于一个Subscriber的对象,isPushed也是这个对象的其中一个属性,这个不是业务逻辑,而是标识Subscriber对象本身的一个属性。只不过代码中没有显性定义一个isPushed,而是通过 pushedVersion 来同时表达isPushed。

dbl-x commented

感觉好像没理解我表达的意思。

  1. 如果这四个类代表的是一类数据,比如代码中的StoreData(他们确实都实现了StoreData),那他们应该都是一类存储数据,存储数据上显然不应该有类似下面的代码:
    image

  2. Publisher\Subscriber\Watcher代表的都是什么,他们三个是三个名词,代表的是一个Pub动作或者Sub动作上来吗?UnPublisher不是一个名词