gRPC之應該注意的地方

weixin_33907511發表於2016-03-21

記錄一下閱讀gRPCOC原始碼時看到的問題

沒有暴露設定超時時間的介面

GRPCCompletionQueue.m裡面可以看到相關程式碼,可以看到超時時間是const,外部無法修改,相當於一個預設的超時時間

const int64_t kGRPCCompletionQueueDefaultTimeoutSecs = 60;

同時下面的處理也有點囧

...
gpr_timespec deadline = (timeoutSecs < 0)
          ? gpr_inf_future(GPR_CLOCK_REALTIME)
          : gpr_time_from_seconds(timeoutSecs, GPR_CLOCK_REALTIME);
      while (YES) {
        // The following call blocks until an event is available or the deadline elapses.
        grpc_event event = grpc_completion_queue_next(unmanagedQueue, deadline, NULL);
        GRPCQueueCompletionHandler handler;
        switch (event.type) {
          case GRPC_OP_COMPLETE:
            handler = (__bridge_transfer GRPCQueueCompletionHandler)event.tag;
            handler(event.success);
            break;
          case GRPC_QUEUE_TIMEOUT:
            // Nothing to do here
            break;
          case GRPC_QUEUE_SHUTDOWN:
            grpc_completion_queue_destroy(unmanagedQueue);
            return;
          default:
            [NSException raise:@"Unrecognized completion type" format:@"type=%d", event.type];
        }
...

超時居然不做處理,理應拋個錯誤什麼的吧

網路執行緒完成後回撥在主執行緒

GRXConcurrentWriteable.m中可以看到,回撥時都工作在UI執行緒

// Designated initializer
- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable {
  if (self = [super init]) {
    _writeableQueue = dispatch_get_main_queue();
    _writeable = writeable;
  }
  return self;
}

- (void)enqueueSuccessfulCompletion {
  dispatch_async(_writeableQueue, ^{
    dispatch_once(&_alreadyFinished, ^{
      // Cancellation is now impossible. None of the other three blocks can run concurrently with
      // this one.
      [self.writeable writesFinishedWithError:nil];
      // Skip any possible message to the wrapped writeable enqueued after this one.
      self.writeable = nil;
    });
  });
}

這種設計模式在AFN中有,在gRPC中也有,但是實際應用中我認為問題很大。我個人認為多執行緒程式設計的其中一個最佳實踐就是,哪個執行緒發起非同步任務,回撥時就工作在哪個執行緒,這樣對於呼叫方是最安全的。

相關文章