gRPC Client的負載均衡器


一、gRPC是什么?

gRPC是一個高性能、通用的開源RPC框架,其由Google主要面向移動應用開發並基於HTTP/2協議標准而設計,基於ProtoBuf(Protocol Buffers)序列化協議開發,且支持眾多開發語言。gRPC提供了一種簡單的方法來精確地定義服務和為iOS、Android和后台支持服務自動生成 可靠性很強的客戶端功能庫。客戶端充分利用高級流和鏈接功能,從而有助於節省帶寬、降低的TCP鏈接次數、節省CPU使用、和電池壽命。

二、為什么使用gRPC?

有了 gRPC, 我們可以一次性的在一個 .proto 文件中定義服務並使用任何支持它的語言去實現客戶端和服務器,反過來,它們可以在各種環境中,從Google的服務器到你自己的平板電腦- gRPC 幫你解決了不同語言間通信的復雜性以及環境的不同.使用 protocol buffers 還能獲得其他好處,包括高效的序列號,簡單的 IDL 以及容易進行接口更新。

三、出現啟動其中一個服務掛了、中間服務掛了、服務重新啟動這三種情況,如何保證客戶端的正常訪問?

1、haproxy

缺點:每次連接都會創建一個channel,並發高的話資源消耗大,這樣性能也會有問題

2、客戶端負載均衡器

優點:單例,資源消耗小,性能比較好

缺點:可能還存在點問題,代碼有點亂

3、zk、consul

以后改進方案

4、如果大家有更好的方案,歡迎大家拍磚,謝謝

四、相關包的引用版本是多少?

1、Grpc.Core.0.15.0

2、Grpc.HealthCheck.0.15.0-beta

3、Google.Protobuf.3.0.0-beta3

五、核心代碼如下:

獲取工作中的服務通道

public static Channel GetWorkingChannel(string key)
    {
      Ensure.NotNullOrEmpty(key);
      CachedItem item = null;
      _cacheMap.TryGetValue(key, out item);
      Channel currentChosenChannel = null;
      if (_cacheMap.IsNotEmpty())
      {
        foreach (var channel in item.Channels.OrderBy(o => Guid.NewGuid()))
        {
          try
          {
            if (channel.State == ChannelState.Idle || channel.State == ChannelState.Ready)
            {
              channel.ConnectAsync(DateTime.Now.AddMilliseconds(100)).Wait();
              currentChosenChannel = channel;
              break;
            }
          }
          catch
          {
            channel.ShutdownAsync().Wait();
          }
        };
      }

      if (currentChosenChannel == null) InitWorkingChannelsByKey(key);
      return currentChosenChannel;
    }

  

進行健康檢查

private static bool CheckIfConnectionIsWorking(Channel serverChannel)
    {
      if (serverChannel != null)
      {
        try
        {
          var client = new Health.HealthClient(serverChannel);
          var response = client.Check(new HealthCheckRequest { Service = "HealthCheck" });
          return response.Status == HealthCheckResponse.Types.ServingStatus.Serving;
        }
        catch (Exception ex)
        {
          serverChannel.ShutdownAsync().Wait();
          return false;
        }
      }
      return false;
    }

  

定時任務維護

 private static void ExecuteMaintenance(object state)
    {
      if (Interlocked.CompareExchange(ref _executing, 1, 0) != 0)
        return;
      try
      {
        if (_cacheMap.Count == 0)
        {
          StopMaintenance();
          if (_cacheMap.Count != 0)
            StartMaintenance();
        }
        else
        {
          DateTime oldThreshold = DateTime.UtcNow - _timeout;
          var expiredItems = _cacheMap.Where(i => i.Value.Updated < oldThreshold).Select(i => i.Key);
          for (int i = 0; i < expiredItems.Count(); i++)
          {
            var key = expiredItems.ElementAt(i);
            DisposeChannelsByKey(key);
            InitWorkingChannelsByKey(key);
          }
        }
      }
      finally
      {
        Interlocked.Exchange(ref _executing, 0);
      }
    }

  

gRPC Client源代碼已上傳git,本人比較懶沒有完整上傳解決方案,該有的都有了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM