由于供应商系统的幂等性服务有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 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{}
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 { return true }
func main() { http.HandleFunc("/process", handleRequest) http.ListenAndServe(":8080", nil) }
|
Bug针对上述代码中的 result
,如果是 false 的情况下,该 Token 的请求处理结果应该记录为 false
, 即 processedRequests[requestID] = false
。
本例子中,供应商的错误在哪里呢?供应商系统的幂等服务,在24小时内,如果出现错误,服务不会重新执行,而是认为已经处理完成,继续抛出同样的 error message。实在不能够接受。