博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebAPi的可视化输出模式(RabbitMQ、消息补偿相关)——所有webapi似乎都缺失的一个功能...
阅读量:5938 次
发布时间:2019-06-19

本文共 4531 字,大约阅读时间需要 15 分钟。

最近的工作我在做一个有关于消息发送和接受封装工作。大概流程是这样的,消息中间件是采用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上是个什么样子的,按照常规设计就是两个字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// <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是获取接受消息列表,就是查看当前消息发送到接受是个什么状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/// <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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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是不是真的缺少了一个可视化模式。

 

 

出处:

分类:
 
 
本文转自左正博客园博客,原文链接: ,如需转载请自行联系原作者
 
你可能感兴趣的文章
Java 位运算
查看>>
好用的CSS模块化打包工具CSS-COMBO
查看>>
python 中的字符和字符串
查看>>
C#Winform限制Textbox只能输入数字
查看>>
EL表达式经典用法
查看>>
java.lang.NoClassDefFoundError: javax/mail/Authenticator
查看>>
联想集团涨超7% 杨元庆持股比例升至8.12%
查看>>
各省光伏十三五规划汇总:总规模将超130GW
查看>>
Apache Storm 官方文档 —— 常用模式
查看>>
聊聊JVM的年轻代
查看>>
lvm逻辑卷管理
查看>>
VS2010不能断点/下断的问题
查看>>
[Android]权限处理
查看>>
Spark bind on port 0. Attempting port 1 问题解决
查看>>
兼容所有浏览器的复制到剪切板功能,悬浮层不能复制问题解决
查看>>
day 20 第一阶段考试总结
查看>>
我的友情链接
查看>>
Centos 7.5 部署DNS
查看>>
yum简介
查看>>
cp讲解
查看>>