1、gRPC是什麼?git
gRPC是一個高性能、通用的開源RPC框架,其由Google主要面向移動應用開發並基於HTTP/2協議標準而設計,基於ProtoBuf(Protocol Buffers)序列化協議開發,且支持衆多開發語言。gRPC提供了一種簡單的方法來精確地定義服務和爲iOS、Android和後臺支持服務自動生成 可靠性很強的客戶端功能庫。客戶端充分利用高級流和連接功能,從而有助於節省帶寬、下降的TCP連接次數、節省CPU使用、和電池壽命。github
2、爲何使用gRPC?服務器
有了 gRPC, 咱們能夠一次性的在一個 .proto 文件中定義服務並使用任何支持它的語言去實現客戶端和服務器,反過來,它們能夠在各類環境中,從Google的服務器到你本身的平板電腦- gRPC 幫你解決了不一樣語言間通訊的複雜性以及環境的不一樣.使用 protocol buffers 還能得到其餘好處,包括高效的序列號,簡單的 IDL 以及容易進行接口更新。併發
3、出現啓動其中一個服務掛了、中間服務掛了、服務從新啓動這三種狀況,如何保證客戶端的正常訪問?負載均衡
一、haproxy框架
缺點:每次鏈接都會建立一個channel,併發高的話資源消耗大,這樣性能也會有問題性能
二、客戶端負載均衡器ui
優勢:單例,資源消耗小,性能比較好設計
缺點:可能還存在點問題,代碼有點亂移動應用開發
三、zk、consul
之後改進方案
四、若是你們有更好的方案,歡迎你們拍磚,謝謝
4、相關包的引用版本是多少?
一、Grpc.Core.0.15.0
二、Grpc.HealthCheck.0.15.0-beta
三、Google.Protobuf.3.0.0-beta3
5、核心代碼以下:
獲取工做中的服務通道
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,本人比較懶沒有完整上傳解決方案,該有的都有了。