独占线程处理sending队列时,同一个服务的消息会不会出现乱序
sniper00 opened this issue · 7 comments
sniper00 commented
- 假如 sending 队列要发送消息到 服务 S ,顺序是:a,b,c,d,e
- 发送 a 时,S blocked, a 被放到 e 后边
- 发送 b 时,S 变为非blocked, 这样 b 就先于 a 被处理了
Line 171 in 53135a9
static void
dispatch_exclusive_sending(struct exclusive_thread *e, struct queue *sending) {
struct ltask *task = e->task;
struct service_pool *P = task->services;
int len = queue_length(sending);
int i;
for (i=0;i<len;i++) {
struct message *msg = (struct message *)queue_pop_ptr(sending);
switch (service_push_message(P, msg->to, msg)) {
case 0 : // succ
break;
case 1 : // block, push back
queue_push_ptr(sending, msg);
break;
default : // dead, delete message
// todo : report somewhere or release object in message
message_delete(msg);
break;
}
if (service_status_get(P, msg->to) == SERVICE_STATUS_IDLE) {
debug_printf(e->logger, "Service %x is in schedule", msg->to.id);
service_status_set(P, msg->to, SERVICE_STATUS_SCHEDULE);
schedule_back(task, msg->to);
}
}
}
cloudwu commented
这是设计之中的
cloudwu commented
解释一下:当 A 向 B 和 C 发消息时,发出的次序和 B C 收到(处理)的次序无关。
所谓消息的次序,只在发送者和接收者固定对上才有意义。
cloudwu commented
如果向同一个服务发送需要保证次序,可以用普通的 send 而不要用批量 send 。
sniper00 commented
那这个批量send主要用于哪些场景?
cloudwu commented
又想了一下。目前 timer 服务是没有问题的;但如果做网络服务有问题。我今天改一下。
cloudwu commented
我加了一个机制来保证同一个服务上的消息次序:当一个服务首次被发现阻塞后,这一批的所有发向该服务的消息都不再发送。
因为服务的消息队列被阻塞是一个罕见状态,所以我用了一个简单的 O(n) 的数据结构来处理这种情况。此处 n 是当前发送队列中处于阻塞状态的服务数量。n 通常不会太大。绝大部分时候 n == 0 。
sniper00 commented
嗯,看样子可以解决这个问题