建筑问题
由于上一篇文章(架构:简单的 CQS),我一直在思考如何构建一个简单的系统,足够灵活,可以在以后进行扩展。
换句话说:我认为现在不需要成熟的 CQRS,但我希望以后如果需要的话可以很容易地发展到它。
所以我正在考虑将命令与查询分开,但两者都基于相同的数据库。
查询部分很简单:基于视图的 WCF 数据服务,可以轻松查询数据。那里没什么特别的。
命令部分比较困难,这里有一个想法:命令当然是以异步方式执行的,因此它们不会返回结果。但是,我的 ASP.NET MVC 站点的控制器经常需要来自命令的反馈(例如,成员注册是否成功)。因此,如果控制器发送命令,它还会生成与命令属性一起传递的事务 ID(guid)。命令服务接收此命令,将其放入数据库中状态为“处理”的事务表中,并执行(使用 DDD 原理)。执行后,事务表会更新,状态变为“已完成”或“失败”,以及其他更详细的信息,例如生成的主键。
同时,该站点正在使用 QueryService 轮询该事务的状态,直到收到“已完成”或“失败”,然后它可以根据此结果继续其工作。如果轮询事务表并且结果为“已完成”或“失败”,则删除该条目。
副作用是我不需要 guid 作为我的实体的键,这对于性能和大小来说是一件好事。
在大多数情况下,可能不需要这种轮询机制,但如果需要的话也是可以的。界面的设计考虑到了 CQS,因此面向未来。
您认为这种方法有什么缺陷吗?还有其他想法或建议吗?
谢谢!
路德
As a result of a previous post (Architecture: simple CQS) I've been thinking how I could build a simple system that is flexible enough to be extended later.
In other words: I don't see the need for a full-blown CQRS now, but I want it to be easy to evolve to it later, if needed.
So I was thinking to separate commanding from querying, but both based on the same database.
The query part would be easy: a WCF data service based on views to that it's easy to query for data. Nothing special there.
The command part is something more difficult, and here's an idea: commands are of course executed in an asynchronous way, so they don't return a result. But, my ASP.NET MVC site's controllers often need feedback from a command (for example if a registration of a member succeeded or not). So if the controller sends a command, it also generates a transaction ID (a guid) that is passed together with the command properties. The command service receives this command, puts it into a transactions table in the database with state 'processing', and is executed (using DDD principles). After execution, the transactions table is updated, so that state becomes 'completed' or 'failed', and other more detailed information like the primary key that was generated.
Meanwhile the site is using the QueryService to poll for the state of this transaction, until it receives 'completed' or 'failed', and then it can continue its work based on this result. If the transactions table is polled and the result was 'completed' or 'failed', the entry is deleted.
A side effect is that I don't need guid's as keys for my entities, which is a good thing for performance and size.
In most cases this polling mechanism is probably not needed, but is possible if needed. And the interfaces are designed with CQS in mind, so open for the future.
Do you think of any flaws in this approach? Other ideas or suggestions?
Thanks!
Lud
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您的方法非常接近完整的 CQRS 系统。
我有一个网站,我曾经做过与您所描述的类似的事情。我的网站 braincredits.com 是使用 CQRS 构建的,所有命令本质上都是异步的。因此,结果是,当我创建条目时,除了命令已成功提交处理(而不是已处理)之外,实际上没有向用户提供任何反馈。
但我在网站上有一个用户分数(他们的“积分”计数),随着用户提交更多项目,该分数应该会改变。但我不希望用户不断按 F5 刷新浏览器。因此,我正在按照您的建议进行操作 - 我有一个 AJAX 调用,每隔一两秒就会触发一次,以查看用户的信用计数是否已更改。如果有,则返回新的金额并更新 UI(用一点动画来吸引用户的注意力 - 但不要太华丽)。
您所说的是最终一致性——用户所看到的应用程序的状态最终将与系统数据(记录系统)保持一致。这个概念对于 CQRS 来说非常关键,而且在我看来,它很有意义。一旦您在系统中检索数据(无论是否基于 CQRS),数据就是旧的。但是,如果您假设这一点并假设客户端最终会保持一致,那么您的方法就有意义,您还可以设计 UI 来考虑这一点并利用这一点。
至于建议,我会观察您进行了多少轮询以及您发送和返回的数据量。一定要过度进行民意调查,听起来你并没有这样做。但目标是在您的网站上定期更新哪些内容,我认为您会做得很好。
查询端的 WCF 数据服务层是一个好主意 - 只需确保它仅启用读取(我确信您已经完成了)。
除此之外,听起来你已经有了一个良好的开端。
我希望这有帮助。祝你好运!
I think you are very close to a full CQRS system with your approach.
I have a site that I used to do something similar to what you are describing. My site, braincredits.com, is architected using CQRS, and all commands are async in nature. So, as a result, when I create an entry, there is really no feedback to the user other than the command was successfully submitted for processing (not that it processed).
But I have a user score on the site (a count of their "credits") that should change as the user submits more items. But I don't want the user to keep hitting F5 to refresh the browser. So I am doing what you are proposing -- I have an AJAX call that fires off every second or two to see if the user's credit count has changed. If it has, the new amount is brought back and the UI is updated (with a little bit of animation to catch the user's attention -- but not too flashy).
What you're talking about is eventual consistency -- that the state of the application that the user is seeing will eventually be consistent with the system data (the system of record). That concept is pretty key to CQRS, and, in my opinion, makes a lot of sense. As soon as you retrieve data in a system (whether it's a CQRS-based one or not), the data is old. But if you assume that and assume that the client will eventually be consistent, then your approach makes sense and you can also design your UI to account for that AND take advantage of that.
As far as suggestions, I would watch how much polling you do and how much data you're sending up and back. Do go overboard with polling, which is sounds like you're not. But target what should be updated on a regular basis on your site and I think you'll be good.
The WCF Data Service layer for the query side is a good idea - just make sure it's only read-enabled (which I'm sure you've done).
Other than that, it sounds like you're off to a good start.
I hope this helps. Good luck!