我正试着绕过AMQP.它看起来很适合应用程序之间的机器间(集群,LAN,WAN)通信,但我不确定它是否适合(在架构和当前实现术语中)用作一台机器中的软件总线.
是否值得提取当前的高性能消息传递框架以用AMQP替换它,或者是否通过模糊本地和非本地通信之间的区别而陷入与RPC相同的陷阱?
我也对使用WAN技术进行机内通信的性能影响保持警惕,尽管这可能比架构更像是一个实现问题.
战争故事将不胜感激.
我目前正在设计一个我最终想要迁移到Windows Azure的应用程序.但是,在短期内,它将在我自己托管的服务器上运行.
该应用程序涉及许多单独的Web应用程序 - 其中一些本质上是接收数据的WCF服务,一些是用户管理数据的站点.此外,还需要在后台运行工作服务,以各种方式处理数据.
我非常渴望为此使用解耦架构.理想情况下,我希望组件(即Web应用程序和工作服务)尽可能少地了解彼此.似乎使用消息队列将是最好的解决方案 - Web应用程序可以将带有工作单元的消息排入队列,工作服务可以将它们挑选出来并根据需要进行处理.
但是,我想制定一套很好的技术来做到这一点,记住我最终会转向Azure,并希望尽量减少迁移到云时我需要做的工作量.Azure内置了一个Queue组件,看起来非常适合我的需求.我想做的是自己创造一些尽可能模仿的东西.
看起来有几个选项(我在Windows上使用.NET,带有SQL Server 2005后端) - 到目前为止我发现的是:
我想知道是否有人对此有任何建议 - 或者是否有人做了类似的事情,并就要做/要避免的事情提出建议.我意识到每种情况都不同,但在这种情况下,我认为我的排队要求非常通用,所以我很想听到别人对最佳方法的看法.
提前致谢,
约翰
在54:53分钟的谈话中,Rich Hickey正在谈论使用队列作为解耦依赖程序部分的手段.你能给我一个例子,说明如何将下面的Java伪代码分离出来,以便改进它的设计和/或灵活性:
// Warning: Java-pseudo-code ahead
class Job {
public void doRun(A a) {
saveObjectToDatabase(a);
B b = computeB(a);
saveObjectToDatabase(b);
C c = computeC(b);
logToFile(c);
}
}
Run Code Online (Sandbox Code Playgroud)
saveObjectToDatabase并且saveObjectToDatabase可以看作具有副作用的方法,而computeB's和computeC's输出仅依赖于a.
我知道这个问题相当模糊/广泛.我想了解如何利用排队机制,而不会使我的程序大规模复杂化,并仍然确保它以正确的顺序做正确的事情.任何指向正确方向的人都会受到赞赏.
我正在考虑系统将通知多个消费者有关一群物体发生的事件.每个订阅者应该能够订阅发生在零个或多个对象上的事件,多个订阅者应该能够接收有关发生在单个对象上的事件的信息.
我认为在这种情况下,某些消息排队系统是合适的,但我不知道如何处理我将拥有数百万个对象的事实 - 对每个对象使用单独的主题听起来不太好[或者是它正好?].
你能否建议我应该采取的方法,甚至可能是一些合理的开源消息排队系统?
更多细节:
在此先感谢您的反馈,并抱歉有些模糊的问题!
我正在向运行Windows Server 2008 R2的计算机上创建的非常标准的消息队列发送消息.
QueueName:
directionsTest
MachineName:
usernameDev
Run Code Online (Sandbox Code Playgroud)
当我尝试将消息发送到队列时,我收到错误.:
队列路径名无效.
我感到困惑的是,我实际上是通过SSMS查询窗口发送此消息,我们有存储过程将这些消息发送到队列,我们只提供机器名称,队列名称和消息.所以,这基本上是我多次使用的保存查询,实际上我在上周末使用了这个完全相同的查询.从那时起,我没有更改查询/我的机器/队列/,并且创建和发送这些消息的存储过程没有改变.所以,我不确定为什么这会给我这个错误.
我已经尝试了太阳下的一切,我尝试在我的计算机上创建新的队列并收到相同的错误.我还确保每个人都可以访问这些队列.关于什么会导致此错误弹出的任何想法?我已经搜索过网络,但我没有发现可能导致此问题的线索.(**我还测试了在不同服务器上发送到队列,这没有错误)
感谢任何建议/方向提前.
每秒只有20条消息!这就是我得到的!这是从队列中查看50条消息并使用ReceiveById并行接收它们的代码.队列中的消息总数是500.我也测试了其他数字.但是上限是每秒20条消息!我在某处完全不受影响吗?
编辑1:
1 - 我需要队列可以恢复.但有趣的是,即使我将可恢复选项设置为false; 仍然是最高限制是20消息/秒.
2 - 我被迫在这里使用MSMQ,因为涉及一些遗留应用程序.但是如果这个代码是正确的并且这个前20个限制确实存在,我可以说服该组切换.因此,任何推荐(基于实际经验)的替换MSMQ都是非常受欢迎的(请注意,如果出现任何类型的失败,我们需要保留我们的消息).
3 - 我已经将ThreadPool中的线程数设置为一个高数字,以防它有所帮助但实际上在这段代码中它将导致创建100 - 200个线程.我已经测试了从50到10000的不同数字,没有差异.
4 - 在每个任务中创建一个新的MessageQueue,因为ReceiveById不是线程安全的.
5 - 正如人们在代码中看到的那样,消息大小非常低; 它只是一个字符串加一个int.
编辑2:[ 非常奇怪的新结果 ]
我已经玩了这段代码的每一点,发现了这个:如果我注释掉行singleLocal.UseJournalQueue = false; 在我的任务中,我每秒最多可以读取1200条消息.不是很令人印象深刻,但在我的情 奇怪的部分是UseJournalQueue的默认值为false; 为什么再将它设置为假应该在性能上有所不同?
static partial class Program
{
static void Main(string[] args)
{
ThreadPool.SetMaxThreads(15000, 30000);
ThreadPool.SetMinThreads(10000, 20000);
var qName = @".\private$\deep_den";
if (!MessageQueue.Exists(qName))
{
var q = MessageQueue.Create(qName);
}
var single = new MessageQueue(qName);
single.UseJournalQueue = false;
single.DefaultPropertiesToSend.AttachSenderId = false;
single.DefaultPropertiesToSend.Recoverable = true;
single.Formatter = new XmlMessageFormatter(new[] { typeof(Data) });
var count …Run Code Online (Sandbox Code Playgroud) 我刚刚起步并运行Kafka 0.8 beta 1.我有一个非常简单的示例启动和运行,问题是,我只能让一个消息消费者工作,而不是几个.也就是说,runSingleWorker()方法可以工作.run()方法不起作用:
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.consumer.ConsumerConfig;
import kafka.javaapi.consumer.ConsumerConnector;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.truecar.inventory.worker.core.application.config.AppConfig;
public class ConsumerThreadPool {
private final ConsumerConnector consumer;
private final String topic;
private ExecutorService executor;
private static ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
public ConsumerThreadPool(String topic) {
consumer = kafka.consumer.Consumer.createJavaConsumerConnector((ConsumerConfig)context.getBean("consumerConfig"));
this.topic = topic;
}
public void shutdown() {
if (consumer != null) consumer.shutdown();
if (executor != null) executor.shutdown();
}
public void run(Integer numThreads) …Run Code Online (Sandbox Code Playgroud) 我正在使用RabbitMQ 我的任务池逐个按顺序运行.但是如何添加时间参数以使任务仅在未来的定义时间运行(如a scheduled tasks).
我正在开发一个Android应用程序,它从Internet获取图像并在用户界面中显示.我正在使用RecyclerView来显示图像.我打算使用单独的线程下载图像.并通过处理程序更新RecyclerView.我不知道这个概念是否正确,(我知道AsyncTask,但出于学习目的,我正在尝试实现Handler.) 所以我的编码与下面相同
private void loadNewsThumbnailImage(ArrayList<DataItem> dataList) {
for (DataItem item : DataList) { //DataItem is the model class
loadThumbnailFromInternet(item);
}
}
private void loadThumbnailFromInternet(final DataItem dataItem) {
Thread imageDowloaderThread = new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmap = null;
try {
bitmap = getDataItemBitmap(dataItem.getmImageUrl());
dataItem.setmThumbnail(bitmap);
new Handler().post(new Runnable() { // Tried new Handler(Looper.myLopper()) also
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
imageDowloaderThread.start();
}
Run Code Online (Sandbox Code Playgroud)
我已执行此代码,但我收到错误,应用程序终止,我不知道为什么会发生这种情况.请任何人帮我解决一下.并解释当前代码的问题.
(请不要建议使用AsyncTask(我已经尝试过,它工作正常)) …
我目前面临一个问题,我可以肯定有一个正式名称,但是我不知道该在网上搜索什么。我希望如果我描述问题和解决方案时想到的,有人能够告诉我设计模式的名称(如果有一个与我要描述的内容相匹配的设计模式)。
基本上,我想拥有一个工作队列:我有多个创建工作的客户端(发布者),以及许多处理这些工作的工人(消费者)。现在,我想将发布者创建的作业分发给各个使用者,这基本上可以使用几乎任何消息队列并在整个队列中实现负载均衡,例如使用RabbitMQ甚至MQTT 5。
但是,现在事情变得复杂了……每个工作都指向一个外部实体,例如一个用户。我想要的是按顺序处理单个用户的作业,但并行处理多个用户的作业。我不要求用户X的作业始终去工作者Y,因为无论如何它们都应按顺序处理。
现在,我可以使用RabbitMQ及其一致的哈希交换来解决此问题,但是当新的工作人员进入集群时,我就会进行数据竞赛,因为RabbitMQ不支持重新定位已经在队列中的作业。
MQTT 5也不支持:在这里,这个想法被称为“粘性共享订阅”,但这不是官方的。它可能是MQTT 6的一部分,也可能不是。谁知道。
我也看过NSQ,NATS和其他一些经纪人。他们中的大多数甚至都不支持这种非常特定的情况,而那些确实使用一致哈希的情况,则存在前面提到的数据竞速问题。
现在,如果代理在作业到达后不将作业分类到队列中,而是跟踪某个特定用户的作业是否已经在处理中,则问题将消失:如果这样,它将延迟所有其他作业该用户,但其他用户的所有作业仍应处理。使用RabbitMQ等人无法做到这一点。
我很确定我不是唯一拥有用例的人。例如,我可以想到用户将视频上传到视频平台,尽管上传的视频是并行处理的,但单个用户上传的所有视频都是按顺序处理的。
因此,简而言之:我所形容的名字是用一个普通名字吗?诸如分布式作业队列之类的东西?具有任务相似性的任务调度程序?还是其他?我尝试了很多术语,但没有成功。这可能意味着没有解决方案,但是如上所述,很难想象我是这个问题上唯一的人。
有什么想法我可以寻找吗?并且:是否有实现此目的的工具?有协议吗?
PS:仅使用预定义的路由密钥是不可行的,因为用户ID(我在这里只是作为一个示例)基本上是UUID,因此可以有数十亿个,因此我需要更多动态的东西。因此,一致性哈希基本上是正确的方法,但是如上所述,为了避免数据争用,分发必须逐个进行而不是预先进行。
distributed design-patterns message-queue dispatcher job-queue
message-queue ×10
distributed ×2
java ×2
msmq ×2
.net ×1
amqp ×1
android ×1
apache-kafka ×1
architecture ×1
azure ×1
c# ×1
decoupling ×1
dispatcher ×1
handler ×1
ibm-mq ×1
job-queue ×1
jobs ×1
mq ×1
performance ×1
python ×1
rabbitmq ×1
scala ×1
sql-server ×1