瀏覽代碼

优化 LocalApiService
Serslot取消请求时LocalApiService的线程等待

lith 4 年之前
父節點
當前提交
6b1a9f6295
共有 19 個文件被更改,包括 465 次插入186 次删除
  1. 53 0
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/Extensions/ILocalApiService_Extensions.cs
  2. 21 0
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService/ILocalApiService.cs
  3. 4 46
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService/LocalApiService.cs
  4. 9 0
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService/LocalApiServiceFactory.cs
  5. 4 4
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/StaticFileTransmit/Extensions/ILocalApiService_StaticFileMap_Extensions.cs
  6. 5 3
      dotnet/Library/Sers/Sers.Core/Test/Sers.Core.Module.LocalApi.MsTest/LocalApi/LocalApiTest.cs
  7. 3 1
      dotnet/Library/Sers/Sers.Core/Test/Sers.Core.Module.LocalApi.Qps/LocalApi/LocalApiTest.cs
  8. 4 4
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/ILocalApiService_LoadSerslotApi_Extensions.cs
  9. 73 0
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/RpcContext_BuildHttpRequestFeature_Extensions.cs
  10. 0 111
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/SerslotServer_ProcessRequest_Extensions.cs
  11. 2 1
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/LocalApiNode.cs
  12. 8 3
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/Extensions/IWebHostBuilder_UseSerslot_Extensions.cs
  13. 67 0
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/Extensions/SerslotServer_ProcessRequest_Extensions.cs
  14. 135 0
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/LocalApiService.cs
  15. 7 7
      dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/SerslotServer.cs
  16. 1 1
      dotnet/Library/Sers/Sers.ServiceStation/Sers.ServiceStation/ServiceStation.cs
  17. 11 1
      dotnet/Library/Vit/Vit.Core/Vit.Core/Extensions/StreamExtensions_ToBytesAsync.cs
  18. 3 3
      dotnet/ServiceCenter/Sers.ServiceCenter/Sers.ServiceCenter/ServiceCenter.cs
  19. 55 1
      dotnet/ServiceStation/Demo/Serslot/Did.Serslot.Demo/Controllers/ValuesController.cs

+ 53 - 0
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/Extensions/ILocalApiService_Extensions.cs

@@ -0,0 +1,53 @@
+using Newtonsoft.Json;
+using Sers.Core.Module.Api.LocalApi;
+using Sers.Core.Module.Api.LocalApi.StaticFileTransmit;
+using Sers.Core.Module.Api.LocalApi.StaticFileTransmit.Extensions;
+using Sers.Core.Module.ApiLoader;
+using Sers.SersLoader;
+using System;
+using System.Reflection;
+using Vit.Core.Module.Log;
+
+
+namespace Vit.Extensions
+{
+    public static partial class ILocalApiService_Extensions
+    {
+
+        #region LoadApi
+
+        //public ApiLoaderMng apiLoaderMng { get; set; } = new ApiLoaderMng();
+
+        /// <summary>
+        /// 从配置文件(appsettings.json  Sers.LocalApiService.ApiLoaders ) 加载api加载器并加载api
+        /// </summary>
+        public static void LoadApi(this ILocalApiService data)
+        {
+            data.ApiNodeMng.AddApiNode(new ApiLoaderMng().LoadApi());
+        }
+
+
+        /// <summary>
+        /// 调用SersApi加载器加载api
+        /// </summary>
+        /// <param name="config"></param>
+        public static void LoadSersApi(this ILocalApiService data,ApiLoaderConfig config)
+        {
+            data.ApiNodeMng.AddApiNode(new Sers.SersLoader.ApiLoader().LoadApi(config));
+        }
+
+        /// <summary>
+        /// 调用SersApi加载器加载api
+        /// </summary>
+        /// <param name="assembly"></param>
+        public static void LoadSersApi(this ILocalApiService data, Assembly assembly)
+        {
+            data.ApiNodeMng.AddApiNode(new Sers.SersLoader.ApiLoader().LoadApi(new ApiLoaderConfig { assembly = assembly }));
+        }
+
+        #endregion
+
+
+
+    }
+}

+ 21 - 0
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService/ILocalApiService.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using Sers.Core.Module.Message;
+
+namespace Sers.Core.Module.Api.LocalApi
+{
+    public interface ILocalApiService 
+    {
+        void Init();
+
+        bool Start();
+        void Stop();
+
+        ApiNodeMng ApiNodeMng { get; }
+
+        IEnumerable<IApiNode> apiNodes { get; }
+
+
+        void CallApiAsync(Object sender, ApiMessage apiRequest, Action<object, ApiMessage> callback);
+    }
+}

+ 4 - 46
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService.cs → dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService/LocalApiService.cs

@@ -5,12 +5,8 @@ using System.Threading;
 using Vit.Extensions;
 using Vit.Core.Module.Log;
 using Sers.Core.Module.Rpc;
-using Sers.Core.Module.ApiLoader;
 using Vit.Core.Util.ConfigurationManager;
-using Vit.Core.Util.Pool;
 using Vit.Core.Util.Threading;
-using System.Reflection;
-using Sers.SersLoader;
 using Sers.Core.CL.CommunicationManage;
 using Sers.Core.CL.MessageOrganize;
 using Sers.Core.Module.Message;
@@ -21,8 +17,8 @@ using System.Runtime.CompilerServices;
 
 namespace Sers.Core.Module.Api.LocalApi
 {
-    public class LocalApiService
-    {        
+    public class LocalApiService: ILocalApiService
+    {
 
         /// <summary>
         /// 后台服务的线程个数(单位个,默认0,代表不开启服务)(appsettings.json :: Sers.LocalApiService.workThreadCount)
@@ -39,53 +35,15 @@ namespace Sers.Core.Module.Api.LocalApi
             LocalApiEventMng.Instance.UseApiTraceLog();
         }
 
-
-        public readonly ApiLoaderMng apiLoaderMng = new ApiLoaderMng();
-
-
-
-
         /// <summary>
         /// 映射  route -> LocalApiNode
         /// </summary>
-        public readonly ApiNodeMng apiNodeMng = new ApiNodeMng();
+        protected readonly ApiNodeMng apiNodeMng = new ApiNodeMng();
 
         public IEnumerable<IApiNode> apiNodes => apiNodeMng.apiNodes;
 
 
-
-
-        #region LoadApi
-
-
-        /// <summary>
-        /// 从配置文件(appsettings.json  Sers.LocalApiService.ApiLoaders ) 加载api加载器并加载api
-        /// </summary>
-        public void LoadApi()
-        {
-            apiNodeMng.AddApiNode(apiLoaderMng.LoadApi());
-        }
-
-
-        /// <summary>
-        /// 调用SersApi加载器加载api
-        /// </summary>
-        /// <param name="config"></param>
-        public void LoadSersApi(ApiLoaderConfig config)
-        {
-            apiNodeMng.AddApiNode(new SersLoader.ApiLoader().LoadApi(config));
-        }
-
-        /// <summary>
-        /// 调用SersApi加载器加载api
-        /// </summary>
-        /// <param name="assembly"></param>
-        public void LoadSersApi(Assembly assembly)
-        {
-            apiNodeMng.AddApiNode(new SersLoader.ApiLoader().LoadApi(new ApiLoaderConfig { assembly = assembly }));
-        }
-
-        #endregion
+        public ApiNodeMng ApiNodeMng => apiNodeMng;  
 
 
 

+ 9 - 0
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/LocalApiService/LocalApiServiceFactory.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Sers.Core.Module.Api.LocalApi
+{
+    public class LocalApiServiceFactory
+    {
+        public static Func<ILocalApiService> CreateLocalApiService = () => new LocalApiService();
+    }
+}

+ 4 - 4
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/StaticFileTransmit/Extensions/LocalApiService_StaticFileMap_Extensions.cs → dotnet/Library/Sers/Sers.Core/Sers.Core/Module/Api/LocalApi/StaticFileTransmit/Extensions/ILocalApiService_StaticFileMap_Extensions.cs

@@ -8,7 +8,7 @@ using Vit.Core.Module.Log;
 
 namespace Vit.Extensions
 {
-    public static partial class LocalApiService_StaticFileMap_Extensions
+    public static partial class ILocalApiService_StaticFileMap_Extensions
     {
   
 
@@ -18,7 +18,7 @@ namespace Vit.Extensions
         /// 从配置文件(appsettings.json::Sers.LocalApiService.staticFiles)加载静态文件映射器
         /// </summary>
 
-        public static void LoadApi_StaticFiles(this LocalApiService data)
+        public static void LoadApi_StaticFiles(this ILocalApiService data)
         {
             if (data == null)
             {
@@ -44,7 +44,7 @@ namespace Vit.Extensions
         }
 
 
-        static void LoadApi_StaticFileMap(LocalApiService data, StaticFilesApiNodeConfig config)
+        static void LoadApi_StaticFileMap(ILocalApiService data, StaticFilesApiNodeConfig config)
         {
 
             #region (x.1)创建并初始化StaticFileMap
@@ -61,7 +61,7 @@ namespace Vit.Extensions
 
             apiNode.apiDesc.description = config.apiName;
             apiNode.apiDesc.name = config.apiName;
-            data.apiNodeMng.AddApiNode(apiNode);
+            data.ApiNodeMng.AddApiNode(apiNode);
 
             var msg = "[LocalApiService] 已加载静态文件映射器";
             msg += "," + Environment.NewLine + "apiName:  " + config.apiName;

+ 5 - 3
dotnet/Library/Sers/Sers.Core/Test/Sers.Core.Module.LocalApi.MsTest/LocalApi/LocalApiTest.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Sers.Core.Module.Api.LocalApi;
 using Sers.Core.Module.LocalApi.MsTest.LocalApi.Extensions;
+using Vit.Extensions;
 
 namespace Sers.Core.Module.LocalApi.MsTest.LocalApi
 {
@@ -13,10 +14,11 @@ namespace Sers.Core.Module.LocalApi.MsTest.LocalApi
         public void TestCall()
         {
             try
-            {          
- 
+            {
+
                 //(x.1)构建
-                LocalApiService localApiService = new LocalApiService() { workThreadCount =1};
+                LocalApiService localApiService = LocalApiServiceFactory.CreateLocalApiService() as LocalApiService;
+                localApiService.workThreadCount = 1;
                 localApiService.LoadSersApi(this.GetType().Assembly);
 
                 try

+ 3 - 1
dotnet/Library/Sers/Sers.Core/Test/Sers.Core.Module.LocalApi.Qps/LocalApi/LocalApiTest.cs

@@ -3,6 +3,7 @@ using Statistics;
 using Sers.Core.Module.Api.LocalApi;
 using Sers.Core.Module.LocalApi.MsTest.LocalApi.Extensions;
 using System.Threading.Tasks;
+using Vit.Extensions;
 
 namespace Sers.Core.Module.LocalApi.MsTest.LocalApi
 {
@@ -16,7 +17,8 @@ namespace Sers.Core.Module.LocalApi.MsTest.LocalApi
         static LocalApiTest()
         {
             //(x.1)构建
-            localApiService = new LocalApiService() { workThreadCount = workThreadCount };
+            localApiService = LocalApiServiceFactory.CreateLocalApiService() as LocalApiService;
+            localApiService.workThreadCount = workThreadCount; 
             localApiService.LoadSersApi(typeof(LocalApiTest).Assembly);
 
             localApiService.Start();

+ 4 - 4
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/LocalApiServiceExtensions.cs → dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/ILocalApiService_LoadSerslotApi_Extensions.cs

@@ -11,7 +11,7 @@ using LocalApiNode = Sers.Serslot.LocalApiNode;
 
 namespace Vit.Extensions
 {
-    public static partial class LocalApiServiceExtensions
+    public static partial class ILocalApiService_LoadSerslotApi_Extensions
     {
         /// <summary>
         /// 调用Serslot加载器加载api
@@ -19,7 +19,7 @@ namespace Vit.Extensions
         /// <param name="data"></param>
         /// <param name="assembly"></param>
         /// <param name="server"></param>
-        public static void LoadSerslotApi(this LocalApiService data, Assembly assembly, SerslotServer server)
+        public static void LoadSerslotApi(this ILocalApiService data, Assembly assembly, SerslotServer server)
         {
             if (null == data)
             {
@@ -27,7 +27,7 @@ namespace Vit.Extensions
             }
             #region (x.1) api from host
             var config = new ApiLoaderConfig { assembly= assembly };
-            data.apiNodeMng.AddApiNode(new  ApiLoader(server).LoadApi(config));
+            data.ApiNodeMng.AddApiNode(new  ApiLoader(server).LoadApi(config));
             #endregion
 
 
@@ -56,7 +56,7 @@ namespace Vit.Extensions
                     apiNode = new ApiNode_Original(onInvoke, apiDesc);
                 }
 
-                data.apiNodeMng.AddApiNode(apiNode);
+                data.ApiNodeMng.AddApiNode(apiNode);
             });            
             #endregion
 

+ 73 - 0
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/RpcContext_BuildHttpRequestFeature_Extensions.cs

@@ -0,0 +1,73 @@
+using System;
+using Microsoft.AspNetCore.Http.Features;
+using Sers.Core.Module.Rpc;
+using System.IO;
+using Microsoft.AspNetCore.Http;
+using System.Runtime.CompilerServices;
+
+namespace Vit.Extensions
+{
+    internal static partial class RpcContext_BuildHttpRequestFeature_Extensions
+    {
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static HttpRequestFeature BuildHttpRequestFeature(this RpcContext rpcContext)
+        {
+            HttpRequestFeature requestFeature;
+
+            #region build requestFeature
+
+            ArraySegment<byte> arg_OriData = rpcContext.apiRequestMessage.value_OriData;
+            var rpcData = rpcContext.rpcData;
+
+            // "http://127.0.0.1/Station1/fold1/a/1/2.html?c=9"
+            var http_url = rpcData.http.url;
+            Uri uri = new Uri(http_url);
+            //var Query = Uri.UnescapeDataString(uri.Query);
+            var Query = uri.Query;
+            var AbsolutePath = Uri.UnescapeDataString(uri.AbsolutePath);
+            //var AbsolutePath = uri.AbsolutePath;
+
+            requestFeature = new HttpRequestFeature
+            {
+                Body = new MemoryStream(arg_OriData.Array, arg_OriData.Offset, arg_OriData.Count),
+                Headers = new HeaderDictionary(),
+                Protocol = rpcData.http.protocol,
+                Scheme = uri.Scheme,
+                Method = rpcData.http.method,
+                PathBase = "",
+                QueryString = uri.Query,
+
+                Path = AbsolutePath,
+                RawTarget = AbsolutePath,
+
+            };
+
+            #region http header
+            if (rpcData.http.headers != null)
+                foreach (var t in rpcData.http.headers)
+                {
+                    requestFeature.Headers[t.Key] = t.Value;
+                }
+            #endregion
+
+            //var requestFeature = new HttpRequestFeature
+            //{
+            //    Body = new MemoryStream(),
+            //    Protocol = "HTTP/2.0",
+            //    Scheme = "http",
+            //    Method = "GET",
+            //    PathBase = "",
+            //    Path = "/api/values",
+            //    QueryString = "",
+            //    RawTarget = "/api/values"
+            //};
+            #endregion
+
+            return requestFeature;
+        }
+
+
+
+    }
+}

+ 0 - 111
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/SerslotServer_ProcessRequest_Extensions.cs

@@ -1,111 +0,0 @@
-using Microsoft.AspNetCore.Http.Features;
-using Sers.Core.Module.Rpc;
-using System;
-using System.IO;
-using Microsoft.AspNetCore.Http;
-using Sers.Serslot;
-using System.Runtime.CompilerServices;
-
-namespace Vit.Extensions
-{
-    public static partial class SerslotServer_ProcessRequest_Extensions
-    {
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static byte[] ProcessRequestByRpc(this SerslotServer data, ArraySegment<byte> arg_OriData)
-        {
-            HttpRequestFeature requestFeature = null;
-            IHttpResponseFeature responseFeature = null;
-            try
-            {
-                var rpcData = RpcContext.RpcData;
-
-                #region (x.1) build requestFeature
-                // "http://127.0.0.1/Station1/fold1/a/1/2.html?c=9"
-                var http_url = rpcData.http.url;
-                Uri uri = new Uri(http_url);
-                //var Query = Uri.UnescapeDataString(uri.Query);
-                var Query = uri.Query;
-                var AbsolutePath = Uri.UnescapeDataString(uri.AbsolutePath);
-                //var AbsolutePath = uri.AbsolutePath;
-
-                requestFeature = new HttpRequestFeature
-                {
-                    Body = new MemoryStream(arg_OriData.Array, arg_OriData.Offset, arg_OriData.Count),
-                    Headers = new HeaderDictionary(),
-                    Protocol = rpcData.http.protocol,
-                    Scheme = uri.Scheme,
-                    Method = rpcData.http.method,
-                    PathBase = "",
-                    QueryString = uri.Query,
-
-                    Path = AbsolutePath,
-                    RawTarget = AbsolutePath,
-
-                };
-
-                #region http header
-                if (rpcData.http.headers != null)
-                    foreach (var t in rpcData.http.headers)
-                    {
-                        requestFeature.Headers[t.Key] = t.Value;
-                    }
-                #endregion
-
-                //var requestFeature = new HttpRequestFeature
-                //{
-                //    Body = new MemoryStream(),
-                //    Protocol = "HTTP/2.0",
-                //    Scheme = "http",
-                //    Method = "GET",
-                //    PathBase = "",
-                //    Path = "/api/values",
-                //    QueryString = "",
-                //    RawTarget = "/api/values"
-                //};
-                #endregion
-
-
-                #region (x.2) ProcessRequest
-                responseFeature = data.ProcessRequest(requestFeature);
-                #endregion
-
-
-                #region (x.3)build reply info
-                var rpcReply = new RpcContextData();
-
-                //(x.x.1)StatusCode
-                rpcReply.http.statusCode=responseFeature.StatusCode;
-
-                #region (x.x.2)http_header
-                var replyHeader = responseFeature.Headers;
-                if (replyHeader != null)
-                {
-                    var headers = rpcReply.http.Headers();
-                    foreach (var item in replyHeader)
-                    {
-                        headers[item.Key] = item.Value.ToString();
-                    }
-                }
-                #endregion
-
-                //(x.x.3)
-                RpcContext.Current.apiReplyMessage.rpcContextData_OriData = rpcReply.ToBytes().BytesToArraySegmentByte();
-                #endregion
-
-                #region (x.4) return reply data
-                return (responseFeature.Body as MemoryStream).ToArray();
-                #endregion
-
-            }
-            finally
-            {
-                requestFeature?.Body?.Dispose();
-                responseFeature?.Body?.Dispose();
-            }
-
-        }
-
-
-
-    }
-}

+ 2 - 1
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/LocalApiNode.cs

@@ -25,7 +25,8 @@ namespace Sers.Serslot
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public byte[] Invoke(ArraySegment<byte> arg_OriData)
         {
-            return server.ProcessRequestByRpc(arg_OriData);
+            throw new NotImplementedException();
+            //return server.ProcessRequestByRpc(arg_OriData);
         }       
 
 

+ 8 - 3
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Extensions/WebHostBuilderSerslotExtensions.cs → dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/Extensions/IWebHostBuilder_UseSerslot_Extensions.cs

@@ -3,11 +3,12 @@ using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Hosting.Server;
 using Microsoft.Extensions.DependencyInjection;
 using Newtonsoft.Json.Linq;
+using Sers.Core.Module.Api.LocalApi;
 using Sers.Serslot;
 
 namespace Vit.Extensions
 {
-    public static partial class WebHostBuilderSerslotExtensions
+    public static partial class IWebHostBuilder_UseSerslot_Extensions
     {
         public static IWebHostBuilder UseSerslot(this IWebHostBuilder hostBuilder)
         {
@@ -17,11 +18,15 @@ namespace Vit.Extensions
             }
 
 
+
             var server = new SerslotServer();
             server.InitPairingToken(hostBuilder);
-       
+
+            LocalApiServiceFactory.CreateLocalApiService = () => new Sers.Serslot.LocalApiService(server);
+
+
             return hostBuilder.ConfigureServices(services =>
-            {                 
+            {
                 services.AddSingleton<IServer>((serviceProvider)=> {
                     server.serviceProvider = serviceProvider;
                     return server;

+ 67 - 0
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/Extensions/SerslotServer_ProcessRequest_Extensions.cs

@@ -0,0 +1,67 @@
+using Microsoft.AspNetCore.Http.Features;
+using Sers.Core.Module.Rpc;
+using System.IO;
+using Sers.Serslot;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace Vit.Extensions
+{
+    public static partial class SerslotServer_ProcessRequest_Extensions
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static async Task ProcessRequestByRpcAsync(this SerslotServer data, RpcContext rpcContext)
+        {
+         
+            HttpRequestFeature requestFeature = null;
+            IHttpResponseFeature responseFeature = null;
+            try
+            {
+                //(x.1) build requestFeature
+                requestFeature = rpcContext.BuildHttpRequestFeature();
+
+                //(x.2) ProcessRequest
+                responseFeature = await data.ProcessRequestAsync(requestFeature);         
+
+
+                #region (x.3)build reply
+                var rpcReply = new RpcContextData();
+
+                //(x.x.1)StatusCode
+                rpcReply.http.statusCode = responseFeature.StatusCode;
+
+                #region (x.x.2)http_header
+                var replyHeader = responseFeature.Headers;
+                if (replyHeader != null)
+                {
+                    var headers = rpcReply.http.Headers();
+                    foreach (var item in replyHeader)
+                    {
+                        headers[item.Key] = item.Value.ToString();
+                    }
+                }
+                #endregion
+
+                //(x.x.3) reply rpcContextData
+                rpcContext.apiReplyMessage.rpcContextData_OriData = rpcReply.ToBytes().BytesToArraySegmentByte();
+
+
+                #region (x.x.4) reply Body
+                var body = (responseFeature.Body as MemoryStream).ToArray();
+                rpcContext.apiReplyMessage.value_OriData = body.BytesToArraySegmentByte();
+                #endregion
+
+                #endregion
+            }
+            finally
+            {
+                requestFeature?.Body?.Dispose();
+                responseFeature?.Body?.Dispose();
+            }
+
+        }
+
+
+
+    }
+}

+ 135 - 0
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/LocalApiService.cs

@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Vit.Extensions;
+using Vit.Core.Module.Log;
+using Sers.Core.Module.Rpc;
+using Sers.Core.Module.Message;
+using Vit.Core.Util.ComponentModel.SsError;
+using Sers.Core.Module.Api.LocalApi.Event;
+using System.Runtime.CompilerServices;
+using Sers.Core.Module.Api.LocalApi;
+using System.Threading.Tasks;
+
+namespace Sers.Serslot
+{
+    public class LocalApiService: ILocalApiService
+    {
+
+        public LocalApiService(SerslotServer serslotServer) 
+        {
+            this.serslotServer = serslotServer;
+        }
+
+
+
+
+        public void Init()
+        {
+            LocalApiEventMng.Instance.UseApiTraceLog();
+        }
+
+        /// <summary>
+        /// 映射  route -> LocalApiNode
+        /// </summary>
+        protected readonly ApiNodeMng apiNodeMng = new ApiNodeMng();
+
+        public IEnumerable<IApiNode> apiNodes => apiNodeMng.apiNodes;
+
+
+        public ApiNodeMng ApiNodeMng => apiNodeMng;
+
+
+        SerslotServer serslotServer;
+
+        #region CallLocalApi
+ 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        async Task  CallLocalApiAsync(ApiMessage apiRequest, Object sender, Action<object, ApiMessage> callback)
+        {           
+            using (var rpcContext = new RpcContext())
+            using (var localApiEvent = LocalApiEventMng.Instance.CreateApiEvent())
+            {
+                try
+                {
+                    //(x.1) init rpcContext
+                    rpcContext.apiRequestMessage = apiRequest;
+                    rpcContext.apiReplyMessage = new ApiMessage();
+
+                    var rpcData = RpcContextData.FromBytes(apiRequest.rpcContextData_OriData);
+                    rpcContext.rpcData = rpcData;
+
+                    //(x.2) BeforeCallApi
+                    localApiEvent?.BeforeCallApi(rpcData, apiRequest);
+
+
+                    // (x.3)ProcessRequestByRpcAsync
+                    await serslotServer.ProcessRequestByRpcAsync(rpcContext);          
+
+                }
+                catch (Exception ex) when ((ex.GetBaseException() is ThreadInterruptedException))
+                {
+                    //处理超时
+                    rpcContext.apiReplyMessage.rpcContextData_OriData = const_ApiReply_Err_Timeout.rpcContextData_OriData;
+                    rpcContext.apiReplyMessage.value_OriData = const_ApiReply_Err_Timeout.value_OriData;
+                    //throw;
+                }
+                catch (Exception ex) when (!(ex.GetBaseException() is ThreadInterruptedException))
+                {
+                    ex = ex.GetBaseException();
+                    Logger.Error(ex);
+                    SsError error = ex;
+                    rpcContext.apiReplyMessage.InitAsApiReplyMessageByError(error);
+                }
+
+                callback(sender, rpcContext.apiReplyMessage);
+            }
+        }
+        #endregion
+
+
+        static readonly ApiMessage const_ApiReply_Err_Timeout = new ApiMessage().InitAsApiReplyMessageByError(SsError.Err_HandleTimeout);
+
+
+        #region 后台服务
+ 
+
+
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void CallApiAsync(Object sender, ApiMessage apiRequest, Action<object, ApiMessage> callback)
+        {
+            CallLocalApiAsync(apiRequest, sender, callback);
+        }
+
+
+
+        #region Start Stop
+
+    
+
+        public bool Start()
+        {
+            return true;
+        }
+
+        public void Stop()
+        {      
+        }
+        #endregion
+
+
+       
+
+        #endregion
+
+
+
+    
+
+
+
+
+
+    }
+}

+ 7 - 7
dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/SerslotServer.cs → dotnet/Library/Sers/Sers.Serslot/Sers.Serslot/Mode/Async/SerslotServer.cs

@@ -36,10 +36,10 @@ namespace Sers.Serslot
 
         #region ProcessRequest       
 
-        Action<FeatureCollection> OnProcessRequest;
+        Func<FeatureCollection,Task> OnProcessRequest;
 
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public IHttpResponseFeature ProcessRequest(HttpRequestFeature requestFeature)
+        public async Task<IHttpResponseFeature> ProcessRequestAsync(HttpRequestFeature requestFeature)
         {
             if (requestFeature.Headers == null)
                 requestFeature.Headers = new HeaderDictionary();
@@ -70,7 +70,7 @@ namespace Sers.Serslot
             }
 
 
-            OnProcessRequest(features);
+            await OnProcessRequest(features);
 
             return _responseFeature;
         }
@@ -275,7 +275,7 @@ namespace Sers.Serslot
             try
             {
                 #region (x.1) build OnProcessRequest               
-                OnProcessRequest = (features) =>
+                OnProcessRequest = async (features) =>
                 {
 
                     Exception _applicationException = null;
@@ -292,11 +292,11 @@ namespace Sers.Serslot
                         //}
 
 
-
-
                         // Run the application code for this request
                         // application.ProcessRequestAsync(httpContext).GetAwaiter().GetResult();
-                        application.ProcessRequestAsync(httpContext).Wait();
+
+                       
+                        await application.ProcessRequestAsync(httpContext);
 
 
                         //var _responseFeature = features.Get<IHttpResponseFeature>() as SerslotResponseFeature;

+ 1 - 1
dotnet/Library/Sers/Sers.ServiceStation/Sers.ServiceStation/ServiceStation.cs

@@ -114,7 +114,7 @@ namespace Sers.ServiceStation
 
         List<IAppEvent> appEventList { get; set; }
 
-        public readonly LocalApiService localApiService = new LocalApiService();
+        public readonly ILocalApiService localApiService = LocalApiServiceFactory.CreateLocalApiService();
 
         private readonly CommunicationManageClient communicationManage = new CommunicationManageClient();
 

+ 11 - 1
dotnet/Library/Vit/Vit.Core/Vit.Core/Extensions/StreamExtensions_ToBytesAsync.cs

@@ -9,6 +9,15 @@ namespace Vit.Extensions
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         public static async Task<byte[]> ToBytesAsync(this Stream data)
         {
+            if (data is MemoryStream ms_) 
+            {
+                if (ms_.Length > 0)
+                {
+                    return ms_.ToArray();
+                }
+                return null;
+            }
+
             using (MemoryStream ms = new MemoryStream())
             {
                 await data.CopyToAsync(ms);
@@ -16,8 +25,9 @@ namespace Vit.Extensions
                 {
                     return ms.ToArray();
                 }
+                return null;
             }
-            return null;
+           
         }
 
 

+ 3 - 3
dotnet/ServiceCenter/Sers.ServiceCenter/Sers.ServiceCenter/ServiceCenter.cs

@@ -81,7 +81,7 @@ namespace Sers.ServiceCenter
 
         private readonly CommunicationManageServer communicationManage = new CommunicationManageServer();
 
-        private readonly LocalApiService localApiService = new LocalApiService();
+        private readonly ILocalApiService localApiService = LocalApiServiceFactory.CreateLocalApiService();
 
         private readonly IOrganizeConnection connForLocalStationService;
 
@@ -91,8 +91,8 @@ namespace Sers.ServiceCenter
         {
             public string connTag { get; set; }
 
-            LocalApiService localApiService;
-            public OrganizeConnection(LocalApiService localApiService)
+            ILocalApiService localApiService;
+            public OrganizeConnection(ILocalApiService localApiService)
             {
                 this.localApiService = localApiService;
             }

+ 55 - 1
dotnet/ServiceStation/Demo/Serslot/Did.Serslot.Demo/Controllers/ValuesController.cs

@@ -1,9 +1,12 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Http.Features;
 using Microsoft.AspNetCore.Mvc;
 using Newtonsoft.Json;
+using Sers.Core.Module.Api;
+using Sers.Core.Module.Rpc;
 using Vit.Core.Util.ComponentModel.Data;
 using Vit.Core.Util.ComponentModel.Model;
 
@@ -22,6 +25,7 @@ namespace Did.Serslot.Demo.Controllers
         /// </summary>
         /// <returns></returns>
         [HttpGet]
+        [HttpPost]
         public object Route0([FromQuery]string a)
         {
             //var requestFeature = Request.HttpContext.Features.Get<IHttpRequestFeature>();             
@@ -437,5 +441,55 @@ namespace Did.Serslot.Demo.Controllers
         }
         #endregion
 
+
+        #region (x.7)ApiClient
+
+        #region (x.x.1)ApiClient示例,调用其他接口
+        /// <summary>
+        /// ApiClient示例,调用其他接口
+        /// </summary>
+        /// <returns></returns>
+
+        [HttpPost("700/ApiClient700")]
+        public ApiReturn<Object> ApiClient700(
+            [SsExample("/did_serslot/Values")] string apiRoute,
+            [SsExample("{\"a\":\"aaa111\"}")] dynamic arg)
+        {
+            var apiRet = ApiClient.CallRemoteApi<string>((string)arg.apiRoute,(object) arg.arg, "POST");
+            return new ApiReturn<Object>(new
+            {
+                RpcContext.RpcData,
+                apiRet
+            });
+        }
+        #endregion
+
+
+        #region (x.x.2)ApiClient示例,调用其他接口
+        /// <summary>
+        /// ApiClient示例,调用其他接口
+        /// </summary>
+        /// <returns></returns>
+
+        [HttpPost("702/ApiClient")]
+        public ApiReturn<Object> ApiClient702()
+        {
+            return new ApiReturn<Object>(new
+            {
+                RpcContext.RpcData
+            });
+        }
+
+
+        [HttpPost("703/ApiClient")]
+        public string ApiClient703()
+        {
+            var rpc=RpcContext.RpcData;
+            var apiRet = ApiClient.CallRemoteApi<string>("/did_serslot/v1/702/ApiClient", null,"POST");
+            return apiRet;
+        }
+        #endregion
+
+        #endregion
     }
 }