.net core实践系列之短信服务-Api的SDK的实现与测试
前言
上一篇《.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现》讲解了API的设计与实现,本篇主要讲解编写接口的SDK编写还有API的测试。
或许有些人会认为,SDK的编写可以不需要,既然已经用了RESTful web服务与Swagger提供的接口描述,只要选择合适的接口调用框架,找到对应Swagger文档按需调用即可。
这个我赞同,特别在微服务架构下使用了API网关与服务发现。因此本篇也是借用编写SDK来模拟在客户端使用接口框架调用,并增加负载测试的讲解,供需要的朋友们分享。
项目源码地址:https://github.com/SkyChenSky/Sikiro.SMS.git
SDK
Software Development Kit的缩写,翻译中文为软件开发工具包,百度定义为软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等创建应用软件的开发工具的集合。而我们这里的SDK主要是以工具库的形式提供给部门内部使用API。
设计要点
- 尽量少的依赖
- 多形式方法重载
- 高可读性
从上三点得出,高可读的方法注释,方便使用的多重载(单条、多条、异步、同步),如涉及到枚举,不要依赖原有项目的其他库,应拷贝过来完整提供。
组件选择
- RestSharp
- .Net Standard
RestSharp
为了良好的调用RESTful API,我选择RestSharp这个RESTful接口调用框架。
源码地址:https://github.com/restsharp/RestSharp
优点
请求调用与响应结果的直观化:
步骤:
- 传入资源
- 定义动作
- 设置表述类型
- 传入实体参数
注意点
1.默认序列化类型为XML,应手动设置为JSON
RequestFormat = DataFormat.Json
2.反序列化有缺陷,对于实体内的类类型属性(List<T>、自定义类等),应再构造函数初始化赋默认值
public class SearchResponse
{
public SearchResponse()
{
Mobiles = new List<string>();
} public string Content { get; set; }
public int Type { get; set; }
public int Status { get; set; }
public List<string> Mobiles { get; set; } [SerializeAs(Name = "_id", Attribute = true)]
public string Id { get; set; }
}
示例
public static class Sms
{
private static RestClient _client; private static string Host { get; set; } public static void Init(string host)
{
Host = host;
_client = new RestClient(Host);
} public static async Task<Response> SendAsync(List<SendEntity> sendList)
{
var request = new RestRequest("sms", Method.POST) { RequestFormat = DataFormat.Json }; request.AddBody(sendList); var response = await _client.ExecuteTaskAsync(request); return ToResponse(response);
} public static async Task<Response> SendAsync(SendEntity sendEntity)
{
return await SendAsync(new List<SendEntity> { sendEntity });
} public static Response Send(List<SendEntity> sendList)
{
var request = new RestRequest("sms", Method.POST) { RequestFormat = DataFormat.Json }; request.AddBody(sendList); var response = _client.Execute(request); return ToResponse(response);
} public static Response Send(SendEntity sendEntity)
{
return Send(new List<SendEntity> { sendEntity });
} public static Response<SearchResponse> Get(string id)
{
var request = new RestRequest("sms/{id}", Method.GET); request.AddUrlSegment("id", id); var response = _client.Execute<SearchResponse>(request); return ToResponse(response);
} public static Response<List<SearchResponse>> Search(SearchEntity searchModel)
{
var request = new RestRequest("sms/_search", Method.POST) { RequestFormat = DataFormat.Json };
request.AddBody(searchModel); var response = _client.Execute<List<SearchResponse>>(request); return ToResponse(response);
} private static Response<T> ToResponse<T>(IRestResponse<T> t)
{
var msg = t.IsSuccessful ? t.StatusCode.ToString() : t.Content;
return new Response<T> { Body = t.Data, StateCode = t.StatusCode, Message = t.ErrorMessage ?? msg, IsSuccess = t.IsSuccessful };
} private static Response ToResponse(IRestResponse t)
{
var msg = t.IsSuccessful ? t.StatusCode.ToString() : t.Content;
return new Response { StateCode = t.StatusCode, Message = t.ErrorMessage ?? msg, IsSuccess = t.IsSuccessful };
}
}
.Net Standard
公司里除了有新用的.NET Core项目还有大量的存量.NET Framework旧项目。
.NET Standard是一种规范,无法以此建立应用,但他能以库的形式作为支撑。.NET Standard的出现为了解决以编写一次的库来同时支持多个平台(.NET Framework、.NET Core、Xamarin)的使用。
为了实现多平台的API标准映射,不同版本的映射与数量也随着不一样
.NET Standard
|
1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 | 2.0 |
---|---|---|---|---|---|---|---|---|
.NET Core | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 |
.NET Framework | 4.5 | 4.5 | 4.5.1 | 4.6 | 4.6.1 | 4.6.1 | 4.6.1 | 4.6.1 |
Mono | 4.6 | 4.6 | 4.6 | 4.6 | 4.6 | 4.6 | 4.6 | vNext |
Xamarin.iOS | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | vNext |
Xamarin.Android | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | vNext |
Universal Windows Platform | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | vNext | vNext | vNext |
Windows | 8.0 | 8.0 | 8.1 | |||||
Windows Phone | 8.1 | 8.1 | 8.1 | |||||
Windows Phone Silverlight | 8.0 |
.Net Standard编译多版本程序集设置
右键编辑项目.csproj,可见下图原本应该是TargetFramework的节点,改为TargetFrameworks(多了个s),通过分号区分不同的程序集,因为RestSharp需要到.NET Framework4.6支持,因为我填入了net46。
接口测试
单元测试
百度定义:单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。
单元:可以是C语言中单元指一个函数,C#、Java里单元指一个类。总的来说,单元就是人为规定的最小的被测功能模块。
然而我的示例代码里的单元测试并非正统规范的单元测试,而是利用单元测试项目来做接口的测试并做负载测试的可运行代码。因此大家不必学习我的做法。
这里有微软的官方文档XUnit结合了
mock框架,可供大家学习传送门
负载测试
百度定义:负载测试是模拟实际软件系统所承受的负载条件的系统负荷,通过不断加载(如逐渐增加模拟用户的数量)或其它加载方式来观察不同负载下系统的响应时间和数据吞吐量、系统占用的资源(如CPU、内存)等,以检验系统的行为和特性,以发现系统可能存在的性能瓶颈、内存泄漏、不能实时同步等问题。
1.对于使用VS2017的可以先到工具-获取工具与功能,勾上Web性能与负载工具
2.添加Web性能和负载测试项目,该项目只能是.NET Framework
3.添加负载测试,并选择本地负载测试,负载测试持续时间是此方案的测试总时间,测试迭代是测试方案的测试总次数
4.输入方案场景名称,并选择思考时间,思考时间可以理解成客户操作的停顿时间。
5.常量负载指模拟的每次测试固定并发数,分级负载则是模拟并发数持续递增。
6.选择需要进行负载测试的单元测试,上面我们编写SDK的单元测试来进行接口测试,因此我们可以选择Send单元测试方法,进行测试接口的性能如何。
7.点击完成,并运行负载测试
8.漫长的等待之后可以查看测试结果与关系图
需要注意的是,做负载测试的时候需要模拟并发请求,这里是占资源的,因此尽量把测试服务放到服务器上测试。
.net core实践系列之短信服务-Api的SDK的实现与测试的更多相关文章
- .net core实践系列之短信服务-目录
前言 经过两周多的业余时间,终于把该系列的文章写完了.第一次写系列,可能部分关键点并没有覆盖到,如果有疑问的朋友可以随时反馈给我.另外也感谢在我发布文章时给予我方案建议与反馈源码BUG的朋友们.下面是 ...
- .net core实践系列之短信服务-Sikiro.SMS.Bus服务的实现
前言 前两篇<.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现>.<.net core实践系列之短信服务-Api的SDK的实现与测试>分别讲解了AP ...
- .net core实践系列之短信服务-架构设计
前言 上篇<.net core实践系列之短信服务-为什么选择.net core(开篇)>简单的介绍了(水了一篇).net core.这次针对短信服务的架构设计和技术栈的简析. 源码地址:h ...
- .net core实践系列之短信服务-Sikiro.SMS.Api服务的实现
前言 上篇<.net core实践系列之短信服务-架构设计>介绍了我对短信服务的架构设计,同时针对场景解析了我的设计理念.本篇继续讲解Api服务的实现过程. 源码地址:https://gi ...
- .net core实践系列之短信服务-架构优化
前言 通过前面的几篇文章,讲解了一个短信服务的架构设计与实现.然而初始方案并非100%完美的,我们仍可以对该架构做一些优化与调整. 同时我也希望通过这篇文章与大家分享一下,我的架构设计理念. 源码地址 ...
- .net core实践系列之短信服务-为什么选择.net core(开篇)
前言 从今天我将会写.net core实战系列,以我最近完成的短信服务作为例子.该系列将会尽量以最短的时间全部发布出来.源码也将优先开源出来给大家. 源码地址:https://github.com/S ...
- .net core实践系列之短信服务-Sikiro.SMS.Job服务的实现
前言 本篇会继续讲解Sikiro.SMS.Job服务的实现,在我写第一篇的时候,我就发现我当时设计的架构里Sikiro.SMS.Job这个可以选择不需要,而使用MQ代替.但是为了说明调度任务使用实现也 ...
- php 阿里云短信服务及阿里大鱼实现短信验证码的发送
一:使用阿里云的短信服务 ① 申请短信签名 ②申请短信模板 ③创建Access Key,获取AccessKeyId 与 AccessKeySecret.(为了安全起见,这里建议使用子用户的Access ...
- PHP开发实用-阿里短信服务(Short Message Service)
步骤 1 使用阿里云短信服务正常发短信需要 短信签名 短信模板 1申请短信签名 根据用户属性来创建符合自身属性的签名信息.企业用户需要上传相关企业资质证明,个人用户需要上传证明个人身份的证明. ...
随机推荐
- synchronized的锁问题
有一个类A,提供了三个方法.分别是静态同步方法,非静态同步方法,含有静态代码块的方法 1 class A{ 2 public static synchronized void print1(){ 3 ...
- python常用模块之pickle
python1个json模块和1个pickle模块都是用于序列化的模块. 其中前文介绍过json模块.json模块只能序列化普通字符,比如字典.列表等.但是如果是函数呢?json其实是无法序列化的.这 ...
- [20170927]关于hugepages.txt
[20170927]关于hugepages.txt --//今天测试hugepages与内核参数nr_overcommit_hugepages,才发现HugePages_Surp表示什么? --// ...
- [MapReduce_1] 运行 Word Count 示例程序
0. 说明 MapReduce 实现 Word Count 示意图 && Word Count 代码编写 1. MapReduce 实现 Word Count 示意图 1. Map:预 ...
- 解决eclipse启动慢
每次启动eclipse时都要等待半分钟左右,对于追求效率的程序员来说,等待每一秒都是一种折磨,出于高效开发的精神,这个问题必须解决掉.方案如下: ①在工具栏中的help中找到about eclipse ...
- Windows编程的本质
既然Windows API编程是与Windows操作系统进行交互,所以就必须对Windows操作系统如何运行应用程序的原理搞清楚. 1.保护模式 操作系统是依附于cpu硬件的,所以操作系统所具备的功能 ...
- Python3编写网络爬虫06-基本解析库Beautiful Soup的使用
二.Beautiful Soup 简介 就是python的一个HTML或XML的解析库 可以用它来很方便的从网页中提取数据 0.1 提供一些简单的 python式的函数来处理导航,搜索,修改分析树等功 ...
- Sublime Text3如何快速预览html文件
Sublime Text3 步骤1:选择 Tools----> Build System ----> New Build System... 步骤2:输入以下内容 "cmd&qu ...
- Html body的滚动条禁止与启用
在写一个在页面中,经验证用户没有登录或session失效时候弹出登录框禁止页面滚动用到今天搞了一个功能,上下左右居中,模仿QQ空间里的样式,把横向和纵向滚动条禁止掉代码如下:<script ty ...
- c++のurlmon实现下载文件并进度回调
主文件: #include "stdafx.h" #include <UrlMon.h> #pragma comment(lib, "urlmon.lib&q ...