当前位置: 首页 > news >正文

dotnet core高吞吐Http api服务组件FastHttpApi

简介

是dotNet core下基于Beetlex实现的一个高度精简化和高吞吐的HTTP API服务开源组件,它并没有完全实现HTTP SERVER的所有功能,而是只实现了在APP和WEB中提供数据服务最常用两个指令GET/SET,满足在应用实现JSON,PROTOBUF和MSGPACK等基于HTTP的数据交互功能,虽然是一个精简版本但针对SSL这方面的安全性还是支持。有牺牲就必然有收获,FastHttpApi作出这么大的精简必然在性能上有所收获取,经测试FastHttpApi在GET/POST这些数据交互的场景下性能和吞吐能力是Asp.net core集成的Kestrel的要优胜许多。

https://github.com/IKende/FastHttpApi

使用便利性

FastHttpApi虽然在HTTP方面作了大量的精简,但并没有为此增加了它使用的复杂度。FastHttpApi具备asp.net core webapi的便利性;应用人员只需要制定和webapi一样的方法即可,在使用过程中和写普通逻辑方法没有多大的区别。

定义一个控制器

控制器用来定义具体相应URL处理的方法,只需要在类上定义Controller属性即可把类中的Public方法提供给Http访问;方法参数来源于QueryString,当参数标记为BodyParameter的时候参数来源于Http Body.

   [Controller]
    public class ControllerTest
    {
        //  /hello?name=
        public string Hello(string name)
        {
            return DateTime.Now + " hello " + name;
        }
        // /add?a=&b=
        public string Add(int a, int b)
        {
            return string.Format("{0}+{1}={2}", a, b, a + b);
        }
        // /post?name=
        public object Post(string name, [BodyParameter] UserInfo data)
        {
            return data;
        }
        // /listcustomer?count
        public IList<Customer> ListCustomer(int count)
        {
            return Customer.List(count);
        }
        // /listemployee?count
        public IList<Employee> ListEmployee(int count)
        {
            return Employee.List(count);
        }
        // post /AddEmployee 
        public Employee AddEmployee([BodyParameter]Employee item)
        {
            return item;
        }
    }
Filter定义

Filter是Controller处理方法的拦载器,通Filter可以对所有方法进行统一拦载处理,如权限日志等。

    [Controller]
    [NotFoundFilter]
    public class ControllerTest
    {
        //  /hello?name=
        [SkipFilter(typeof(NotFoundFilter))]
        [CustomFilter]
        public string Hello(string name)
        {
            return DateTime.Now + " hello " + name;
        }
        // /add?a=&b=
        public string Add(int a, int b)
        {
            return string.Format("{0}+{1}={2}", a, b, a + b);
        }
    }
    public class GlobalFilter : FilterAttribute
    {
        public override void Execute(ActionContext context)
        {
            Console.WriteLine(DateTime.Now + " globalFilter execting...");
            context.Execute();
            Console.WriteLine(DateTime.Now + " globalFilter executed");
        }
    }

    public class NotFoundFilter : FilterAttribute
    {
        public override void Execute(ActionContext context)
        {
            Console.WriteLine(DateTime.Now + " NotFoundFilter execting...");
            context.Response.NotFound();
            Console.WriteLine(DateTime.Now + " NotFoundFilter executed");
        }
    }

    public class CustomFilter : FilterAttribute
    {
        public override void Execute(ActionContext context)
        {
            Console.WriteLine(DateTime.Now + " CustomFilter execting...");
            context.Execute();
            Console.WriteLine(DateTime.Now + " CustomFilter executed");
        }
    }
启动服务
        static void Main(string[] args)
        {
            mApiServer = new BeetleX.FastHttpApi.HttpApiServer();
            mApiServer.Register(typeof(Program).Assembly);
            mApiServer.ServerConfig.BodySerializer = new BeetleX.FastHttpApi.JsonBodySerializer();
            mApiServer.Open();
            Console.Read();
        }

制定HTTP Body转换器

转换器是组件最常用的自定义功能,通过它可以实现不同种类的数据格式,如json,protobuf和msgpack等。以下是一个json转换器的实现

 public class JsonBodySerializer : IBodySerializer
    {
        public JsonBodySerializer()
        {
            ContentType = "application/json";
        }
        public string ContentType { get; set; }
        public object GetInnerError(Exception e, HttpResponse response, bool outputStackTrace)
        {
            return new ErrorResult { url = response.Request.Url, code = 500, error = e.Message, stackTrace = outputStackTrace? e.StackTrace:null };
        }
        public object GetNotSupport(HttpResponse response)
        {
            return new ErrorResult { url = response.Request.Url, code = 403, error = response.Request.Method + " method type not support" };
        }
        public object GetNotFoundData(HttpResponse response)
        {
            return new ErrorResult { url = response.Request.Url, code = 404 };
        }
        public class ErrorResult
        {
            public string url { get; set; }
            public int code { get; set; }
            public string error { get; set; }
            public string stackTrace { get; set; }
        }
        public virtual int Serialize(PipeStream stream, object data)
        {
            int length = stream.CacheLength;
            string value = Newtonsoft.Json.JsonConvert.SerializeObject(data);
            stream.Write(value);
            return stream.CacheLength - length;
        }
        public virtual bool TryDeserialize(PipeStream stream, int length, Type type, out object data)
        {
            data = null;
            if (stream.Length >= length)
            {
                string value = stream.ReadString(length);
                if (type != null)
                {
                    data = Newtonsoft.Json.JsonConvert.DeserializeObject(value,type);
                }
                else
                {
                    data = Newtonsoft.Json.JsonConvert.DeserializeObject(value);
                }
                return true;
            }
            return false;
        }
    }

性能对比测试

由于dotnet core下面没有其他简化的http api组件,只能拿Kestrel asp.net core来作对比,虽然对asp.net core不公平,但这样的对比测也只是为了体现简化后的性能回报;测试服务器是阿里云的4核虚拟机,8G内存,测试工具是AB,测试功能主要是针对GET/POST的json数据处理。由于Kestrel asp.net core默认不支持AB的Keep-Alive选项,所以测试结果就并没有针对asp.net core的Keep-Alive测试

Kestrel asp.net core代码
        // GET api/values/5
        [HttpGet("{id}")]
        public ActionResult Get(int id)
        {
            return new JsonResult(Employee.List(id));
        }
        // POST api/values
        [HttpPost]
        public ActionResult Post([FromBody] Employee value)
        {
            return new JsonResult(value);
        }
FastHttpApi 代码
        // /listemployee?count
        public IList<Employee> ListEmployee(int count)
        {
            return Employee.List(count);
        }
        // post /AddEmployee 
        public Employee AddEmployee([BodyParameter]Employee item)
        {
            return item;
        }
Kestrel asp.net core GET测试结果

FastHttpApi GET测试结果

FastHttpApi GET测试结果开启Keep-Alive

Kestrel asp.net core POST测试结果

FastHttpApi POST测试结果

FastHttpApi POST测试结果开启Keep-Alive

针对Kestrel的对比测试

对比一下两者在accept connection上的性能差异,开启了两个AB实例同时进行压测,结果是FastHttpApi在处理并发数快高于Kestrel快一倍的情况,CPU使用率只有Kestrel的一半。

Kestrel代码
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.Run(context =>
            {
                byte[] data = System.Text.Encoding.UTF8.GetBytes(DateTime.Now.ToString());
                return context.Response.Body.WriteAsync(data, 0, data.Length);
            });
        }
FastHttpApi代码
        //  /hello?name=
        public string Hello(string name)
        {
            return DateTime.Now + " hello " + name;
        }
Kestrel测试结果

FastHttpApi测试结果

相关文章:

  • 第四十一天
  • 秒级展现的百万级大清单报表怎么做
  • Confluence 6 属性的一个活动
  • 怎样寻回参数错误K盘的资料
  • Hibernate防止setter()方法更新数据库
  • 中国象棋残局库构建[抄]
  • java的四个访问权限修饰符的作用范围
  • arts-week10
  • 三剑客老大——awk企业实战,面试必备
  • 快讯 | 嘉益仕受邀在工博会期间参与研华物联网共创全球峰会
  • 曲率计算公式推导
  • JavaScript标签自定义属性
  • Android TV 开发 (1)
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • MySQL是如何做容器测试的?
  • [case10]使用RSQL实现端到端的动态查询
  • 《Java编程思想》读书笔记-对象导论
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • gulp 教程
  • Hibernate【inverse和cascade属性】知识要点
  • Map集合、散列表、红黑树介绍
  • PHP面试之三:MySQL数据库
  • React 快速上手 - 07 前端路由 react-router
  • SSH 免密登录
  • Tornado学习笔记(1)
  • vue.js框架原理浅析
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 批量截取pdf文件
  • 区块链共识机制优缺点对比都是什么
  • 微信小程序开发问题汇总
  • 我有几个粽子,和一个故事
  • 小李飞刀:SQL题目刷起来!
  • NLPIR智能语义技术让大数据挖掘更简单
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #ubuntu# #git# repository git config --global --add safe.directory
  • #Ubuntu(修改root信息)
  • (2)(2.10) LTM telemetry
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (六)Hibernate的二级缓存
  • (四)图像的%2线性拉伸
  • (算法)Travel Information Center
  • .Family_物联网
  • .NET 5种线程安全集合
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET Standard 的管理策略
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .NET是什么
  • /bin/bash^M: bad interpreter: No such file or directory
  • @ConditionalOnProperty注解使用说明
  • @property @synthesize @dynamic 及相关属性作用探究