您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關使用.net core怎么實現微服務,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
遠程服務客戶端代理
public class RemoteServiceProxy : IApiService { public string Address { get; set; } //服務地址private ApiActionResult PostHttpRequest(string interfaceId, string methodId, params object[] p) { ApiActionResult apiRetult = null; using (var httpClient = new HttpClient()) { var param = new ArrayList(); //包裝參數 foreach (var t in p) { if (t == null) { param.Add(null); } else { var ns = t.GetType().Namespace; param.Add(ns != null && ns.Equals("System") ? t : JsonConvert.SerializeObject(t)); } } var postContentStr = JsonConvert.SerializeObject(param); HttpContent httpContent = new StringContent(postContentStr); if (CurrentUserId != Guid.Empty) { httpContent.Headers.Add("UserId", CurrentUserId.ToString()); } httpContent.Headers.Add("EnterpriseId", EnterpriseId.ToString()); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var url = Address.TrimEnd('/') + $"/{interfaceId}/{methodId}"; AppRuntimes.Instance.Loger.Debug($"httpRequest:{url},data:{postContentStr}"); var response = httpClient.PostAsync(url, httpContent).Result; //提交請求 if (!response.IsSuccessStatusCode) { AppRuntimes.Instance.Loger.Error($"httpRequest error:{url},statuscode:{response.StatusCode}"); throw new ICVIPException("網絡異常或服務響應失敗"); } var responseStr = response.Content.ReadAsStringAsync().Result; AppRuntimes.Instance.Loger.Debug($"httpRequest response:{responseStr}"); apiRetult = JsonConvert.DeserializeObject<ApiActionResult>(responseStr); } if (!apiRetult.IsSuccess) { throw new BusinessException(apiRetult.Message ?? "服務請求失敗"); } return apiRetult; } //有返回值的方法代理 public T Invoke<T>(string interfaceId, string methodId, params object[] param) { T rs = default(T); var apiRetult = PostHttpRequest(interfaceId, methodId, param); try { if (typeof(T).Namespace == "System") { rs = (T)TypeConvertUtil.BasicTypeConvert(typeof(T), apiRetult.Data); } else { rs = JsonConvert.DeserializeObject<T>(Convert.ToString(apiRetult.Data)); } } catch (Exception ex) { AppRuntimes.Instance.Loger.Error("數據轉化失敗", ex); throw; } return rs; } //沒有返回值的代理 public void InvokeWithoutReturn(string interfaceId, string methodId, params object[] param) { PostHttpRequest(interfaceId, methodId, param); } }
遠程服務端http接入段統一入口
[Route("api/svc/{interfaceId}/{methodId}"), Produces("application/json")] public async Task<ApiActionResult> Process(string interfaceId, string methodId) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ApiActionResult result = null; string reqParam = string.Empty; try { using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) { reqParam = await reader.ReadToEndAsync(); } AppRuntimes.Instance.Loger.Debug($"recive client request:api/svc/{interfaceId}/{methodId},data:{reqParam}"); ArrayList param = null; if (!string.IsNullOrWhiteSpace(reqParam)) { //解析參數 param = JsonConvert.DeserializeObject<ArrayList>(reqParam); } //轉交本地服務處理中心處理 var data = LocalServiceExector.Exec(interfaceId, methodId, param); result = ApiActionResult.Success(data); } catch BusinessException ex) //業務異常 { result = ApiActionResult.Error(ex.Message); } catch (Exception ex) { //業務異常 if (ex.InnerException is BusinessException) { result = ApiActionResult.Error(ex.InnerException.Message); } else { AppRuntimes.Instance.Loger.Error($"調用服務發生異常{interfaceId}-{methodId},data:{reqParam}", ex); result = ApiActionResult.Fail("服務發生異常"); } } finally { stopwatch.Stop(); AppRuntimes.Instance.Loger.Debug($"process client request end:api/svc/{interfaceId}/{methodId},耗時[ {stopwatch.ElapsedMilliseconds} ]毫秒"); } //result.Message = AppRuntimes.Instance.GetCfgVal("ServerName") + " " + result.Message; result.Message = result.Message; return result; }
本地服務中心通過接口名和方法名,找出具體的實現類的方法,并使用傳遞的參數執行,ps:因為涉及到反射獲取具體的方法,暫不支持相同參數個數的方法重載.僅支持不同參數個數的方法重載.
public static object Exec(string interfaceId, string methodId, ArrayList param) { var svcMethodInfo = GetInstanceAndMethod(interfaceId, methodId, param.Count); var currentMethodParameters = new ArrayList(); for (var i = 0; i < svcMethodInfo.Paramters.Length; i++) { var tempParamter = svcMethodInfo.Paramters[i]; if (param[i] == null) { currentMethodParameters.Add(null); } else { if (!tempParamter.ParameterType.Namespace.Equals("System") || tempParamter.ParameterType.Name == "Byte[]") { currentMethodParameters.Add(JsonConvert.DeserializeObject(Convert.ToString(param[i]), tempParamter.ParameterType) } else { currentMethodParameters.Add(TypeConvertUtil.BasicTypeConvert(tempParamter.ParameterType, param[i])); } } } return svcMethodInfo.Invoke(currentMethodParameters.ToArray()); } private static InstanceMethodInfo GetInstanceAndMethod(string interfaceId, string methodId, int paramCount) { var methodKey = $"{interfaceId}_{methodId}_{paramCount}"; if (methodCache.ContainsKey(methodKey)) { return methodCache[methodKey]; } InstanceMethodInfo temp = null; var svcType = ServiceFactory.GetSvcType(interfaceId, true); if (svcType == null) { throw new ICVIPException($"找不到API接口的服務實現:{interfaceId}"); } var methods = svcType.GetMethods().Where(t => t.Name == methodId).ToList(); if (methods.IsNullEmpty()) { throw new BusinessException($"在API接口[{interfaceId}]的服務實現中[{svcType.FullName}]找不到指定的方法:{methodId}"); } var method = methods.FirstOrDefault(t => t.GetParameters().Length == paramCount); if (method == null) { throw new ICVIPException($"在API接口中[{interfaceId}]的服務實現[{svcType.FullName}]中,方法[{methodId}]參數個數不匹配"); } var paramtersTypes = method.GetParameters(); object instance = null; try { instance = Activator.CreateInstance(svcType); } catch (Exception ex) { throw new BusinessException($"在實例化服務[{svcType}]發生異常,請確認其是否包含一個無參的構造函數", ex); } temp = new InstanceMethodInfo() { Instance = instance, InstanceType = svcType, Key = methodKey, Method = method, Paramters = paramtersTypes }; if (!methodCache.ContainsKey(methodKey)) { lock (_syncAddMethodCacheLocker) { if (!methodCache.ContainsKey(methodKey)) { methodCache.Add(methodKey, temp); } } } return temp;
服務配置,指示具體的服務的遠程地址,當未配置的服務默認為本地服務.
[ { "ServiceId": "XZL.Api.IOrderService", "Address": "http://localhost:8801/api/svc" }, { "ServiceId": "XZL.Api.IUserService", "Address": "http://localhost:8802/api/svc" } ]
AppRuntime.Instance.GetService<TService>()
的實現.
private static List<(string typeName, Type svcType)> svcTypeDic; private static ConcurrentDictionary<string, Object> svcInstance = new ConcurrentDictionary<string, object>(); public static TService GetService<TService>() { var serviceId = typeof(TService).FullName; //讀取服務配置 var serviceInfo = ServiceConfonfig.Instance.GetServiceInfo(serviceId); if (serviceInfo == null) { return (TService)Activator.CreateInstance(GetSvcType(serviceId)); } else { var rs = GetService<TService>(serviceId + (serviceInfo.IsRemote ? "|Remote" : ""), serviceInfo.IsSingle); if (rs != null && rs is RemoteServiceProxy) { var temp = rs as RemoteServiceProxy; temp.Address = serviceInfo.Address; //指定服務地址 } return rs; } } public static TService GetService<TService>(string interfaceId, bool isSingle) { //服務非單例模式 if (!isSingle) { return (TService)Activator.CreateInstance(GetSvcType(interfaceId)); } object obj = null; if (svcInstance.TryGetValue(interfaceId, out obj) && obj != null) { return (TService)obj; } var svcType = GetSvcType(interfaceId); if (svcType == null) { throw new ICVIPException($"系統中未找到[{interfaceId}]的代理類"); } obj = Activator.CreateInstance(svcType); svcInstance.TryAdd(interfaceId, obj); return (TService)obj; } //獲取服務的實現類 public static Type GetSvcType(string interfaceId, bool? isLocal = null) { if (!_loaded) { LoadServiceType(); } Type rs = null; var tempKey = interfaceId; var temp = svcTypeDic.Where(x => x.typeName == tempKey).ToList(); if (temp == null || temp.Count == 0) { return rs; } if (isLocal.HasValue) { if (isLocal.Value) { rs = temp.FirstOrDefault(t => !typeof(RemoteServiceProxy).IsAssignableFrom(t.svcType)).svcType; } else { rs = temp.FirstOrDefault(t => typeof(RemoteServiceProxy).IsAssignableFrom(t.svcType)).svcType; } } else { rs = temp[0].svcType; } return rs; }
為了性能影響,我們在程序啟動的時候可以將當前所有的ApiService類型緩存.
public static void LoadServiceType() { if (_loaded) { return; } lock (_sync) { if (_loaded) { return; } try { svcTypeDic = new List<(string typeName, Type svcType)>(); var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; var dir = new DirectoryInfo(path); var files = dir.GetFiles("XZL*.dll"); foreach (var file in files) { var types = LoadAssemblyFromFile(file); svcTypeDic.AddRange(types); } _loaded = true; } catch { _loaded = false; } } } //加載指定文件中的ApiService實現 private static List<(string typeName, Type svcType)> LoadAssemblyFromFile(FileInfo file) { var lst = new List<(string typeName, Type svcType)>(); if (file.Extension != ".dll" && file.Extension != ".exe") { return lst; } try { var types = Assembly.Load(file.Name.Substring(0, file.Name.Length - 4)) .GetTypes() .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic); foreach (Type type in types) { //客戶端代理基類 if (type == typeof(RemoteServiceProxy)) { continue; } if (!typeof(IApiService).IsAssignableFrom(type)) { continue; } //綁定現類 lst.Add((type.FullName, type)); foreach (var interfaceType in type.GetInterfaces()) { if (!typeof(IApiService).IsAssignableFrom(interfaceType)) { continue; } //綁定接口與實際實現類 lst.Add((interfaceType.FullName, type)); } } } catch { } return lst; }
具體api遠程服務代理示例
public class UserServiceProxy : RemoteServiceProxy, IUserService { private string serviceId = typeof(IUserService).FullName; public void IncreaseScore(int userId,int score) { return InvokeWithoutReturn(serviceId, nameof(IncreaseScore), userId,score); } public UserInfo GetUserById(int userId) { return Invoke<UserInfo >(serviceId, nameof(GetUserById), userId); } }
以上就是使用.net core怎么實現微服務,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。