幂等性服务

由于供应商系统的幂等性服务有bug,经过一番争执,终于说服了对方。现将经由记录如下。

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
┌─────────┐      ┌────────────┐     ┌────────────┐
│ 客户端 │ ┌──►│ 幂等性服务 │ ┌──►│ 数据存储 │
└─────────┘ │ └────────────┘ │ └────────────┘
│ │
│ │
│ ┌───────────┐ │
├──►│ 请求处理 │───┤
│ └───────────┘ │
│ │
│ │
│ ┌───────────┐ │
├──►│ 检查状态 │───┤
│ └───────────┘ │
│ │
│ │
│ ┌───────────┐ │
├──►│ 执行操作 │───┤
│ └───────────┘ │
│ │
│ │
│ ┌───────────┐ │
├──►│ 更新状态 │───┤
│ └───────────┘ │
│ │
└───────────────────┘
  1. 客户端: 这是发起请求的外部实体,可能是用户、其他服务或应用程序。
  2. 幂等性服务: 这是幂等性服务的核心组件,负责接收和处理来自客户端的请求。
  3. 数据存储: 数据存储组件用于存储已处理请求的唯一标识符,以及可能需要的其他相关数据。这可以是数据库、缓存或文件系统等。
  4. 请求处理: 请求处理模块负责解析和验证请求,包括提取唯一标识符和其他请求参数。
  5. 检查状态: 在处理请求之前,服务会检查请求的状态,以确保请求之前未被处理过。这一步骤通常涉及检查唯一标识符是否在数据存储中存在。
  6. 执行操作: 执行操作模块负责实际执行请求所需的操作。这可能包括创建订单、更新资源、执行业务逻辑等。
  7. 更新状态: 更新状态模块负责在请求处理成功后,将请求的唯一标识符添加到数据存储中,以标记该请求已被处理。
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
package main

import (
"fmt"
"net/http"
"sync"
)

// 数据存储:使用映射来存储已处理请求的唯一标识符
var processedRequests = make(map[string]bool)
var mutex = &sync.Mutex{}

// 处理HTTP请求的处理程序函数
func handleRequest(w http.ResponseWriter, r *http.Request) {
// 从请求中获取唯一标识符
requestID := r.Header.Get("Request-ID")
// 使用互斥锁保护共享数据
mutex.Lock()
defer mutex.Unlock()
// 检查请求是否已经处理过
if processedRequests[requestID] {
// 如果已处理过,返回已处理的响应
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Request already processed\n")
} else {
// 如果未处理过,执行请求操作
// 注意:在实际应用中,要确保请求操作是幂等的
result := performRequestOperation(r)
// 更新已处理请求的映射
processedRequests[requestID] = true
// 返回操作结果
if result {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Request processed successfully\n")
} else {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Request processing failed\n")
}
}
}

// 执行请求操作的函数
func performRequestOperation(r *http.Request) bool {
// 在这里执行实际的请求操作,确保操作是幂等的
// 例如,创建订单、更新资源、执行业务逻辑等
// 如果操作成功,返回true;否则返回false
return true
}

func main() {
// 创建HTTP服务器
http.HandleFunc("/process", handleRequest)
http.ListenAndServe(":8080", nil)
}

Bug针对上述代码中的 result ,如果是 false 的情况下,该 Token 的请求处理结果应该记录为 false, 即 processedRequests[requestID] = false
本例子中,供应商的错误在哪里呢?供应商系统的幂等服务,在24小时内,如果出现错误,服务不会重新执行,而是认为已经处理完成,继续抛出同样的 error message。实在不能够接受。