WebAPi的可视化输出模式(RabbitMQ、消息补偿相关)——所有webapi似乎都缺失的一个功能

最近的工作我在做一个有关于消息发送和接受封装工作。大概流程是这样的,消息中间件是采用rabbitmq,为了保证消息的绝对无丢失,我们需要在发送和接受前对消息进行DB落地。在发送前我会先进行DB的插入,单表插入,所以在性能上也是能接受的,单表插入做了压测基本上是一到两毫秒的时间,加上消息的发送(有ACK)再加上集群是两个节点的高可用(一个磁盘持久化节点),单台TPS基本上是在2000-3000左右。这对于我们的业务场景来说是够用了。一旦当消息丢失或者由于网络问题、集群问题业务不会中断,消息就算发不出去也没关系,我们会进行消息的补偿或者同步api调用补偿。这是架构设计的必须要考虑的A计划、B计划、C计划,这是敬畏或者危机意识。

你可能又要说两个节点或者三个节点的集群怎么会有问题,那你就错了,大错特错。只能说明你并不了解什么叫分布式系统及分布式系统的特性。你也许不会知道网络抖动、网络闪断导致socket断开如何进行心跳重试已保持有效的Rabbitmq Connection。当你的网络极不稳定,你的linux keepalived VIP 来回漂移,导致你的ARP根本无法成效,可能就连广播都传不出去,而客户端则在一直使用一个无用的IP地址。当你的集群节点之间无法连接成一个整体的时候各种奇葩的问题又来了。这些都是可能导致你的集群出问题的原因,所以不要大意。

(后面我会整理一篇专门讲解“rabbitmq高可用、故障转移集群架构“文章,所以这里我们就不继续介绍了)

这是一个铺垫,本文的重点是介绍下我在尝试使用可视化webapi的输出模式,这比原本json的输出模式看起来会方便许多。如果你的api提供两种输出模式,人性化绝对很好。现在很多后端api都是没有界面的都是只提供了一个json输出。然而,我们其实很需要一个可读性很强的输出模式。

我在开发消息补偿程序的时候,我借鉴了这一思想进行了尝试。先来看下整体架构蓝图:

本篇文章要介绍的是有关于这个补偿程序的api的可视化输出内容。不涉及到消息相关太多的东西,只是为了让这个可视化输出看起来容易理解点。这个补偿程序需要对发送的消息和接受的消息进行查询和比较然后输出,用来确定消息的发送是失败了还是成功的。简单逻辑就是比较某个时间段内的消息发送表和接受表,然后进行消息id的匹配。

我在想这个数据反馈到api上是个什么样子的,按照常规设计就是两个字段:


/// <summary>
/// 接受的消息对象。
/// </summary>
public  class  ReceiveMessage
{
     /// <summary>
     /// 发送消息ID。
     /// </summary>
     public  string  SendMessageId {  get set ; }
     /// <summary>
     /// 接受消息ID。
     /// </summary>
     public  string  ReceiveMessageId {  get set ; }
}

这表示一个消息从发送到接受的一个过程。如果失败了,可能是只有SendMessageId而没有ReceiveMessageId。然后我才会针对没有ReceiveMessageId的消息进行自动补偿。在开发的时候只有几十条消息,输出到postman中的看起来也还行,但是不直观。

GetReceiveMessage是获取接受消息列表,就是查看当前消息发送到接受是个什么状态。


/// <summary>
/// 处理成功消息对象。
/// </summary>
public  class  SuccessMessage
{
     /// <summary>
     /// 发送消息ID
     /// </summary>
     public  string  SendMessageId {  get set ; }
     /// <summary>
     /// 接受消息ID
     /// </summary>
     public  string  ReceiveMessageId {  get set ; }
     /// <summary>
     /// 处理成功消息ID
     /// </summary>
     public  string  SuccessMessageId {  get set ; }
}

SuccessMessage表示处理成功消息情况。此时有可能是有SendMessageId,ReceiveMessageId消息,但是SuccessMessageId可能是没有的。就会针对处理成功的消息进行发送。

突然受到ElasticSearch的_cat endpoint 启发。似乎这里我可以尝试下,webapi带有两种输出模式,一种是针对程序使用的json输出模式,另外一种是针对人可以阅读的模式text/plain模式,而第二种模式可以简单的理解为是行列转换缺省模式。

是不是看起来会很舒服。这在进行消息的时间段查看非常有帮助,如果还按照原本的json输出模式可能看起来会比较吃力。

来看下基本的api的设计,为了保证你的所有api支持?v可视化模式,需要一定的抽象:

需要定义一种ViewModel,所有的数据都输出这种对象,当然我这里也只是简单地封装。如果可以,其实可以专门提取出一个库出来,包括对文本的输出自动化。

我们看下BaseApiController:


public  class  BaseApiController : ApiController
    {
        public  class  ViewModel
        {
            public  string  Content {  get set ; }
            public  object  JsonObject {  get set ; }
            public  bool  Success =  true ;
        }
        protected  bool  IsView;
        private  const  string  ViewQuerystring =  "?v" ;
        public  ViewModel ResultModel;
        private  const  string  CheckToken =  "CheckToken" ;
        private  const  string  Token =  "49BBD022-CDBF-4F94-80E4-5BCACB1192EC" ;
        private  bool  _checkStatus;
        public  override  Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
        {
            //验证token
            if  (controllerContext.Request.Headers !=  null  && controllerContext.Request.Headers.Contains(CheckToken))
            {
                var  requestToken = controllerContext.Request.Headers.GetValues(CheckToken).FirstOrDefault();
                if  (requestToken !=  null  && requestToken.Equals(Token))
                {
                    this ._checkStatus =  true ;
                }
            }
            if  (!_checkStatus)
            {
                var  checkResult =  new  Task<HttpResponseMessage>(() =>  new  HttpResponseMessage
                {
                    Content =  new  StringContent( "非法访问,缺少token" , Encoding.UTF8,  "text/plain" )
                }, cancellationToken);
                checkResult.Start();
                return  checkResult;
            }
            if  (controllerContext.Request.RequestUri.Query.Equals(ViewQuerystring))
                this .IsView =  true ;
            base .ExecuteAsync(controllerContext, cancellationToken);
            //text模式
            if  ( this .IsView)
            {
                var  textResult =  new  Task<HttpResponseMessage>(() =>  new  HttpResponseMessage
                {
                    Content =  new  StringContent( this .ResultModel.Content, Encoding.UTF8,  "text/plain" )
                }, cancellationToken);
                textResult.Start();
                return  textResult;
            }
            //json模式
            var  resultData =  new  Result< object >
            {
                Data =  this .ResultModel.JsonObject,
                Type =  this .ResultModel.Success ? ResultType.Successfully : ResultType.Failure
            };
            var  jsonResult =  new  Task<HttpResponseMessage>(() =>  new  HttpResponseMessage
            {
                Content =  new  ObjectContent( typeof (Result), resultData,  new  JsonMediaTypeFormatter(),  "application/json" )
            }, cancellationToken);
            jsonResult.Start();
            return  jsonResult;
        }
    }

  

代码很简单,这里给我们一个启发,webapi是不是真的缺少了一个可视化模式

原文地址:http://www.cnblogs.com/wangiqngpei557/p/6107150.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java实现遍历树形菜单方法——Dao层

Dao层接口&#xff1a;/** * Title: IVoteTreeDao.java * Package org.dao * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-5-6 下午10:38:47 * version V1.0 */ package org.dao;import java.util.List;import org.e…

文件损坏 无法删除 怎么使用chkdsk磁盘修复工具

有时候我们会遇到文件无法删除的问题&#xff0c;该如何解决。对于专业人士可能比较简单。对于小白&#xff0c;就够折腾人的了。下面分享下我是怎么做的。 很简单很实用。 现象&#xff1a;此时哪里有损坏&#xff0c;一般会在删除文件时&#xff0c;莫名的提示有文件无法删除…

计算机网络产生的历史背景,网络技术背景及sdn概述.pdf

网络技术背景及sdn概述软件定义网络黄韬北京邮电大学北京邮电大学第1章&#xff1a;背景与概述个人简介个人简介• 黄韬– 信息与通信工程学院– 博士&#xff0c;副教授– 科研方向科研方向&#xff1a;&#xff1a;未来网络未来网络– 教学课程&#xff1a;计算机网络、软件定…

35c3 krautflare

参考这篇文章可以彻底了解本题的漏洞所在 https://xz.aliyun.com/t/6527 由于Math.expm1经过patch以后的返回值不可能是-0&#xff0c;但是patch的地方是在typer优化中&#xff0c;所以实际上如果没有优化的话是可以返回-0的&#xff0c;这就意味着如果我们先不停地Math.expm1…

Java集合框架综述

转载自 Java集合框架综述 集合框架&#xff08;collections framework&#xff09; 首先要明确&#xff0c;集合代表了一组对象&#xff08;和数组一样&#xff0c;但数组长度不能变&#xff0c;而集合能&#xff09;。Java中的集合框架定义了一套规范&#xff0c;用来表示、…

vue项目没有启动成功的原因之一

删除mould。。。本地从新安装

RabbitMQ 高可用集群搭建及电商平台使用经验总结

面向EDA&#xff08;事件驱动架构&#xff09;的方式来设计你的消息AMQP routing key的设计RabbitMQ cluster搭建Mirror queue policy设置两个不错的RabbitMQ plugin 大型应用插件(Sharding、Rederation)Queue镜像失败手动同步各集群配置同步方式&#xff08;RabbitMQ export\i…

java实现遍历树形菜单方法——service层

Service接口&#xff1a; /** * Title: IVoteTreeService.java * Package org.Service * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-5-6 下午10:42:10 * version V1.0 */ package org.Service;import java.util.Li…

谷歌浏览器如何阻止弹窗广告?右下角弹窗一个接一个的弹出 每隔几分钟又来一波 怎么屏蔽?

谷歌浏览器如何阻止弹窗广告&#xff1f;右下角弹窗一个接一个的弹出 每隔几分钟又来一波 怎么屏蔽&#xff1f; 作者&#xff1a;知乎用户 链接&#xff1a;https://www.zhihu.com/question/319190736/answer/645314963 来源&#xff1a;知乎 著作权归作者所有。商业转载请联…

如何线程安全的使用HashMap

转载自 如何线程安全的使用HashMap 在周二面试时&#xff0c;一面的面试官有问到 HashMap 是否是线程安全的&#xff0c;如何在线程安全的前提下使用 HashMap,其实也就是 HashMap&#xff0c;Hashtable&#xff0c;ConcurrentHashMap 和 synchronized Map 的原理和区别。当时有…

脚本可以放在html外,关于把script脚本放在html结束标签外的运行结果???

杨__羊羊在哪里放置 JavaScript 代码&#xff1f;通常情况下&#xff0c;JavaScript 代码是和 HTML 代码一起使用的&#xff0c;可以将 JavaScript 代码放置在 HTML 文档的任何地方。但放置的地方&#xff0c;会对 JavaScript 代码的正常执行会有一定影响&#xff0c;具体如下所…

后端解决跨域问题---SpringBoot

解决跨域问题 在后端解决跨域问题&#xff1a; 新建配置类 config/ CrosConfig.java /*** 解决跨域问题*/ Configuration public class CrosConfig implements WebMvcConfigurer {Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/*…

java实现遍历树形菜单方法——HibernateUtil实现

/** * Title: HibernateUtil.java * Package org.web * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-5-6 下午1:41:30 * version V1.0 */ package org.util;import org.hibernate.Session; import org.hibernate.cfg…

用.net core 写后端—— c++外的另一种选择?

一、.net core简介 &#xff08;1&#xff09;.net是什么 .net实际是遵守同一个标准&#xff08;ECMA&#xff09;的多种不同实现&#xff0c;如.net Framework、Mono、和较新的.netcore。C#是.net支持的其中一种语言&#xff0c;理论上任何遵循公共语言规范&#xff08;CLS&am…

16-就业课(2.1)-应用容器-Docker

https://www.jianshu.com/writer#/notebooks/46975630/notes/74245796 01-今日内容.mp4 02-初始docker-docker概述.mp4 03-初始docker-docker安装.mp4 04-初始docker-docker架构.mp4 05-初始docker-配置镜像加速器.mp4 https://www.jianshu.com/writer#/notebooks/4697563…

如何使ArrayList 线程安全

转载自 如何使ArrayList 线程安全 ArrayList是线程不安全的&#xff0c;轻量级的。如何使ArrayList线程安全&#xff1f; 1、继承Arraylist&#xff0c;然后重写或按需求编写自己的方法&#xff0c;这些方法要写成synchronized&#xff0c;在这些synchronized的方法中调用Arr…

百度地图描绘轨迹html,百度地图API 绘制轨迹历史

DOCTYPE html>2 3 4 5 6 7 body, html{width:100%;height:100%;overflow:hidden;margin:0;font-family:"微软雅黑";}8 #allmap{width:100%;height:100%;overflow:hidden;margin:0;font-family:"微软雅黑";}9 style>10 script>11 script>1213 车…

java实现遍历树形菜单方法——TreeAction实现

/** * Title: TreeAction.java * Package org.web * Description: TODO该方法的主要作用&#xff1a; * author A18ccms A18ccms_gmail_com * date 2017-5-6 下午11:27:32 * version V1.0 */ package org.web;import net.sf.json.JSONArray; import net.sf.json.JSONObje…

传统请求风格 VS RestFul 风格

RestFul 风格 概念 Restful就是一个资源定位及资源操作的风格。不是标准也不是协议&#xff0c;只是一种风格。基于这个风格设计的软件可以更简洁&#xff0c;更有层次&#xff0c;更易于实现缓存等机制。 功能 资源&#xff1a;互联网所有的事物都可以被抽象为资源 资源操…

《微软开源跨平台移动开发实践》团购通知

【新书推荐】《微软开源跨平台移动开发实践》带你走近微软开源开源跨平台技术 大家的响应非常积极&#xff0c;接近400位同学想团购。 这两天通过作者李争的努力&#xff0c;为大家争取到了非常实惠的价格&#xff0c;投票结果看不到具体是谁参与了投票&#xff0c;请参与投票的…