搞定 Cloudflare Pages 优选 IP:从 522 报错到秒开的“偷梁换柱”避坑指南
搞定 Cloudflare Pages 优选 IP:从 522 报错到秒开的“偷梁换柱”避坑指南折腾背景: 最近想给部署在 Cloudflare Pages 上的静态博客(aaaa.com)搞个国内优选 IP 加速。毕竟 Cloudflare 自带的线路在国内“众生平等”地慢,要想速度快,必须得上 Cloudflare for SaaS (Custom Hostnames) 大法。 本以为是个常规操作:开通 SaaS -> 设好 CNAME -> 解析到优选 IP,完事。结果现实直接给我上了一课:Error 522 Connection Timed Out。 折腾了一下午,终于搞明白了其中的逻辑闭环。这不仅仅是配个 DNS 那么简单,这里面藏着一个关于“身份认证”的深坑。为了方便后来人避坑,我把整套逻辑复盘一下。 一、 为什么会翻车?(Error 522 的真相) 我的架构初衷很简单: 用户 访问 aaaa.com。 DNS 指向我的 SaaS 加速域名 cdn.tb.bbbb.com(背后是优选 IP)。 Cloudflare 回源到我的 Pages 源站 my...
Singleflight:深入解析go缓存击穿方案
几乎所有的现代化面向web编程的系统都在关注高并发情况下如何降低下游服务的承接压力,go语言也不例外。go语言在并发方面的发力体现在很多个方面,如更轻量化的协程,原子性操作的atomic,抑制函数重复调用的singleflight等。在常规的业务开发中singleflight使用并不多见,本文将会详细介绍singleflight,以深入理解和探索singleflight更多的技术细节和适用场景。 设计原理singleflight 主要围绕着在高并发环境下对相同 key 的函数调用进行重复抑制。以下是其设计原理的核心要点: Group 结构: singleflight 使用 Group 结构表示一个函数调用的组。每个 Group 对应于一类工作,其中的函数调用可能会有重复的 key。 call 结构: call 结构用于表示一个正在进行中或已完成的函数调用。它包含一个 sync.WaitGroup 用于等待调用的完成,以及相关的结果和错误信息。 重复调用抑制: 在 Do 方法中,首先检查是否已经存在相同 key 的函数调用。如果存在,新的调用将等待已有调用完成...
设计一个几十万TPS的实时位置上报系统
有100w滴滴司机,司机每3s上报一次自己的位置。请你设计一个系统,能够实时将司机的位置存储进系统,并且能够给另外一个系统实时显示路径(每3秒刷新一次最新点),历史数据能够随时查询。 在脉脉上看到这个题目,挺多人讨论。刚好在前司早期也负责做过这块的东西,复刻一下以前的解决方案。 需求分析需求简单拆解可以分为明面上的需求: 位置上报(我之前负责的业务为1s一次上报) 业务实时路径查询 业务历时可查 以及需要解决存在问题和附加需求。 提交的数据怎么防止被恶意刷接口,影响数据准确? 接口响应时间必须要低,以支持几十万的请求。 需要为算法提供数据,以支持路径优化算法在未来变得更加高效。 需要为风控提供数据,以支持业务风控部门内部反作弊的需求。 距离计算,以提供给用户查询实时的距离有多少,以当前速度还需要多久送达。 所以就会多出几个有必要去解决的问题。 数据鉴权,防攻击脏数据 路径优化 路径反作弊 距离计算 技术方案在涉及点位上报前还有生成订单的环节。在生成订单时,订单的目标地址会被推送到算法路径规划的服务中,进行最短路径输出。在前司的业务场景中,因一个配送员存在顺路的情况...
设计一个广告投放平台自动控盘的规则引擎系统
20231109 开始写
Slice的初始化和扩容过程
切片和数组在go语言中都是非常常见的结构,很多刚开始使用go语言的开发者会混淆这两者的概念而留下不少隐藏的bug。本篇会从slice编译期、运行时来分析,以更好理解和掌握slice。 slice概述slice表示一个拥有相同数据类型的可变长度的序列。该序列通过一个较为简单的数据结构实现:https://github.com/golang/go/blob/master/src/runtime/slice.go#L15 12345type slice struct { array unsafe.Pointer len int cap int} 编译期逻辑 编译的整个过程另外开文章说,下面直接讲slice的编译过程。 感兴趣可以先看 src/cmd/compile/main.go 在slice的编译过程中,会调用NewSlice方法,该方法需传入类型为*Type的参数elem,并且返回一个*Type类型的结构体。 1234567891011121314151617181920// NewSlice returns the slice Type wi...
可选方案与技术选型
可选方案与技术选型
Go抽象语法树(AST)实用指南 (二)
grade == “四(3)班” && age > 10 AST 抽象语法树在表达式解析上面也有不错的表现。通常在规则引擎场景可以得到充分的发挥。比如一段表达式 1grade == 四(3)班 && age > 10 这个表达式,对于人来说是非常容易理解的。年级是四(3)班,年纪大于10。 但是计算机来说,传入一段字符串表达式,理解起来可能并不是这么容易。 好在Golang提供了表达式解析的能力,我们可以通过查看解析后的数据,理解ast如果解析这串表达式。 解析表达式1234567891011121314151617181920212223242526272829303132333435 0 *ast.BinaryExpr { 1 . X: *ast.BinaryExpr { 2 . . X: *ast.Ident { 3 . . . NamePos: - 4 . . . Name: "grade" 5 . . . Obj: ...
Go抽象语法树(AST)实用指南 (一)
AST抽象语法树在平时开发一般不太能用到。较多使用场景为代码生成,代码动态解析等等。抽象到具体场景 生成MySQL的model 规则引擎动态解析脚本 本文以另一个使用场景呈现AST的应用场景。 Java下枚举12345678910111213141516171819package com.demo.risk.demo;import lombok.NoArgsConstructor;@NoArgsConstructorpublic enum Status { StatusProcessing(1, "流程中"), StatusPass(2, "通过"), StatusReject(3, "拒绝"); public int Id; public String Name; Status(int id, String name) { this.Id = id; this.Name = name; }} 以上代码定义...
gin的Next()方法使用
使用gin这个web框架开发http服务,少不了使用中间件。 在调用gin.Default()方法的时候就会自动使用Logger和Recovery()两个中间件。 仔细查看两个中间件的实现,你会发现,两个中间件都有c.Next()这个方法的调用。 很多人把Next放在中间的最后一行,然后发现加不加next似乎并没有什么区别。所以,它到底是怎么用的? 来自SF的引用文章:goalng框架Gin中间件的c.Next()有什么作用? 上图可以说是Next()方法的一个形象化的解释 不使用 Next()假设我们去编写这样的一段代码 1234route := gin.Default()route.Use(middleware.RequestID)route.Use(middleware.Log)route.GET("/", app.Index) 而middleware.RequestID的实现如下 12345func RequestID(ctx *gin.Context) { log.Println("request start") ...
gin的Abort()方法使用
gin的Abort()方法使用 食用本篇文章,请先看完Gin的Next()方法使用 简单的Http服务的实现先来实现一个简单的http服务 123456789101112131415161718192021222324package mainimport ( "github.com/gin-gonic/gin" "github.com/jinfeijie/blog-demo/post-837/middleware/md1" "github.com/jinfeijie/blog-demo/post-837/middleware/md2" "github.com/jinfeijie/blog-demo/post-837/middleware/md3" "github.com/jinfeijie/blog-demo/post-837/middleware/md4" "net/http")func main() { router := gin.New() ...










