互联网分布式服务设计 - 接口基础协议
一、目录大纲
- 接口基础协议
- 接口一致性模式(同步&异步)
- 接口授权&签名
- 接口限流&熔断模式
- 接口性能优化技巧
二、接口基础协议
内网服务接口,通用协议定义在HttpGet、HttpPost协议两种。对于接口定义,我们通常采用基于Restful协议定义约束,提供给我们的业务方调用。
通用的请求类,我们习惯性分为两种:带分页和不带分页的请求,带分页的请求,我们一般定义如下数据结构
public class RequestBase { public RequestBase(); public bool allow_paging { get; set; } public int page_index { get; set; } public int page_size { get; set; } public string order_by { get; set; } public bool if_asc { get; set; } public int skip { get; } }
业界对于接口协议返回数据结构,一般定义如下:
public class ResponseBase{ public bool success { get; set; } public string code { get; set; } public string errorMsg { get; set; } public T data { get; set; } }
对于文件流操作上传HttpPost的接口,例如采用Form表单提交,并上传图片流
////// 使用Post方法获取字符串结果 /// /// /// Post表单内容 /// /// 默认20秒 /// 响应内容的编码类型(默认utf-8) /// public static string PostForm(string url, List formItems, CookieContainer cookieContainer = null, string refererUrl = null, Encoding encoding = null, int timeOut = 20000) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); #region 初始化请求对象 request.Method = "POST"; request.Timeout = timeOut; request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; request.KeepAlive = true; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"; if (!string.IsNullOrEmpty(refererUrl)) request.Referer = refererUrl; if (cookieContainer != null) request.CookieContainer = cookieContainer; if (url.StartsWith("https")) { ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback((object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => { return true; }); } #endregion string boundary = "----" + DateTime.Now.Ticks.ToString("x");//分隔符 request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary); //请求流 var postStream = new MemoryStream(); #region 处理Form表单请求内容 //是否用Form上传文件 var formUploadFile = formItems != null && formItems.Count > 0; if (formUploadFile) { //文件数据模板 string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" + "\r\nContent-Type: application/octet-stream" + "\r\n\r\n"; //文本数据模板 string dataFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"" + "\r\n\r\n{1}"; foreach (var item in formItems) { string formdata = null; //上传文件 formdata = string.Format( fileFormdataTemplate, item.Key, //表单键 item.FileName); //统一处理 byte[] formdataBytes = null; //第一行不需要换行 if (postStream.Length == 0) formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2)); else formdataBytes = Encoding.UTF8.GetBytes(formdata); postStream.Write(formdataBytes, 0, formdataBytes.Length); //写入文件内容 if (item.FileContent != null && item.FileContent.Length > 0) { postStream.Write(item.FileContent, 0, item.FileContent.Length); } } //结尾 var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); postStream.Write(footer, 0, footer.Length); } else { request.ContentType = "application/x-www-form-urlencoded"; } #endregion request.ContentLength = postStream.Length; #region 输入二进制流 if (postStream != null) { postStream.Position = 0; //直接写入流 Stream requestStream = request.GetRequestStream(); byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0) { requestStream.Write(buffer, 0, bytesRead); } ////debug //postStream.Seek(0, SeekOrigin.Begin); //StreamReader sr = new StreamReader(postStream); //var postStr = sr.ReadToEnd(); postStream.Close();//关闭文件访问 } #endregion HttpWebResponse response = (HttpWebResponse)request.GetResponse(); if (cookieContainer != null) { response.Cookies = cookieContainer.GetCookies(response.ResponseUri); } using (Stream responseStream = response.GetResponseStream()) { using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.UTF8)) { string retString = myStreamReader.ReadToEnd(); return retString; } } }
////// 表单数据项 /// public class FormItemModel { /// /// 表单键,request["key"] /// public string Key { set; get; } /// /// 表单值,上传文件时忽略,request["key"].value /// public string Value { set; get; } /// /// 上传的文件名 /// public string FileName { set; get; } /// /// 上传的文件内容 /// public byte[] FileContent { set; get; } }
调用示例:
var content = PostForm(reqUrl, new List() { new FormItemModel() { Key = "image_fn", Value = "", FileName = "1.jpg", FileContent = request.image_fn } });
三、接口一致性模式(同步&异步)
参考文章 https://blog.csdn.net/qq_42192693/article/details/120391725
接口一致性模式包括
1、纯DB模式交互: 尽量控制DB拆分原则,在同一数据库实例下,通过DB的ACID特性保证事务一致性
2、DB+分布式服务组合:
无中心化的微服务架构进行有效的拆分实现敏捷开发和自动化部署,并且在海量用户请求下,提高微服务架构细粒度的水平伸缩能力。
细粒度的水平伸缩能力。
四、接口授权&签名
五、接口限流&熔断模式
六、接口性能优化技巧