todo list
mysql事务,外键复习
````begonia源码app层
````begonia源码logic层
````begonia源码dispatch层
io标准包理解与学习
字典树学习
压缩字典树学习
gin源码radix tree部分
gin源码serveHttp部分
keycenter阅读源码
begonia代码生成模式使用 仓仓子出锅了
分布式锁理解
begonia设计文档阅读
阻塞锁,非阻塞锁,自旋锁,互斥锁等概念的理解
gorilla/websocket包文档阅读
反射学习
begonia串讲
作用
begonia是一个RPC框架,可以实现远程函数调用。
在下面这张网校项目架构图中,以加密中心keycenter为例,它提供了CreateToken,RefreshToken等方法,这些方法许多项目都要调用。
而当把keycenter暴露的方法注册到服务中心上运行的begonia之后,这些项目可以像调用本地方法一样方便的去调用keycenter注册的方法。
原理
函数远程调用的过程可以简化为:客户端把需要调用函数的入参序列化并传递给服务端,服务端接受后反序列化后本地执行获得结果,把结果序列化传递再给客户端,最后客户端反序列化,获得结果。
为什么不用http请求
在刚接触RPC概念的时候,一直有一个疑问:http请求似乎也可以实现上述功能,那为什么还会出现RPC?
原因是http在传输的过程中有用信息占比少,请求头包含了大量臃肿的信息,使得它的效率并不高,其次,在部分场景下,确实可以用http请求代替RPC使用。
begonia节点
在集群模式下,begonia除了客户端和服务端外,还有一个服务中心节点。
服务端向服务中心注册服务,服务中心会保存服务相关信息,当客户端发起调用后, ...
Golang Context包
golang的context用于控制并发,下面这篇文章很不错。
https://blog.csdn.net/m0_37645820/article/details/106144342
leetcode刷题题解
剑指offer 03
题面
https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/
思考
淼题
有两种思路,一种是时间换空间,对数组进行排序,扫一遍出结果;另一种类似桶排序,是用空间换时间。
不过在解题时,出现了一些问题,由于之前写算法题一直使用c++,而且写golang时习惯用IDE
自动提示,导致go语法记不熟,出现了下面这段鬼畜的代码:
1234567891011func findRepeatNumber(nums []int) int { len := nums.len var a [len]int for k, v := range nums { if a[v] != 0 { fmt.Println(v) break } ++a[v] }}
这段代码有几个问题:
求一个切片的长度应该用len(Slice)
不能用变量给数组设置大小(至于为什么可以联想一下之前学的CSAPP)
k没 ...
gin源码阅读:tree部分
作用
gin框架的tree部分用于处理url和handle的映射关系
比如有这样一些路由:
1234engine.GET("/api/user/:uid/info", u.getInfo)engine.GET("/api/user/:uid/essay/:eid", u.getUserEssay)engine.POST("/api/user/:uid/essay", u.UploadUserEssay)...
这里的每一组url都要精确的对应到一个HandleFunc方法,考虑到性能要求,gin框架使用了基数树(即压缩字典树)作为底层数据结构,关于字典树以及基数树的前置知识可以参见:
https://wuhaoda.life/2021/03/31/字典树学习笔记/
https://blog.csdn.net/qq_17308321/article/details/89736691
这是一个存储了字符串的基数树,和gin最终呈现的很相似。
源码
基数树的定义
123456type methodTree struct ...
字典树学习
最近想看一看gin源码,听说gin底层基于压缩字典树,于是想先复习一下字典树知识。
Trie(字典树)用于字符串的快速检索,其每个节点都有若干个字符指针,若在插入或者检索字符串时扫描到一个字符c,就沿着当前节点的c字符指针,走向该指针指向的节点。
初始化
一颗空Trie仅包含一个根节点,该点的字符指针均指向空。
以一个装小写字母的Trie举例:
1int trie[SIZE][26], tot = 1;
插入
直接上代码吧,感觉挺容易理解的。
12345678910void insert(char* str) { int len = strlen(str), p = 1; //p是指针 for (int k = 0; k < len; ++k) { int ch = str[k] - 'a'; if (trie[p][ch] == 0) trie[p][ch] = ++tot; //tot是地址,从1开始递,如果字符ch没有出现过就给它新建个节点,地址tot自增 p ...
golang反射学习
这里只说一下golang中反射的作用,使用方法和原理不谈
反射的作用
当不知道类型的时候,可以通过反射来实现更新变量、运行时查看值、调用方法以及直接对他们的布局进行操作。
情景
比如需要一个函数来处理一个值,但是值的类型不确定,若用一般方法,需要用.(type)来获取值类型,然后用一连串的switch来分类讨论,而使用反射就可以在不知道类型的情况下对值进行操作。
具体功能
获取变量内部信息
struct的反射
匿名或嵌入字段的反射
判断传入的类型是否是我们想要的类型
通过反射修改内容
通过反射调用方法
参考
https://blog.csdn.net/u011957758/article/details/81193806
链表
最近看到面试算法题经常出现链表相关的题目,但是由于时间久远+oi中链表并不经常出现,我的链表知识已经还给刘汝佳了,遂恶补一通
定义
1234struct ListNode { int value; ListNode* next;};
两个字段:一个是值,一个是指向下个节点指针。
添加节点
1234567891011121314151617181920212223void AddToTail(ListNode** pHead, int value) { //new node ListNode* pNew = new ListNode(); pNew->value = value; pNew->next = NULL; //head judge if (*pHead == NULL) { *pHead = pNew; } else { //find tail ListNode* pNode = new ListNode(); pNode = *pHead; while (pNode->next ! ...
中台理解
在看begonia的设计文档的时候,发现了这样一张图
其中的中台这个词还是第一次听说,百度之。
传统架构
传统的服务架构是这样的:
每一个前台的用户终端都需要与后台进行一次对接,而后台的每一个模块都需要维持与前台业务的关联,并根据不同业务前台的特征加入适配。
可以看到这里前台和后台的耦合性非常强,后台的每一个项目都需要加入与前台适配的部分,增加了开发量,当后台需要对服务升级或者架构调整的时候,还需要考虑与前台的对接,及其麻烦~~(又想到了当初的寒假作业)~~
中台业务架构
当引入中台之后,中台就作为了一个对接层,统一对接前端的不同终端,对后台的各个系统进行封装。
一句话总结:用一句话来概括就是:中台的核心本质就是服务共享,目标是支持前台的快速创新或试错,而实现的手段是微服务架构、敏捷基础设施和公共基础服务。
回到begonia
再回头看begonia的架构图,图中的中台服务大概是指前端接口一类的东西,这里之所以用中台服务大概是中台服务已经是项目中非常普遍的做法了吧。
分布式锁学习笔记
阅读keycenter的时候发现了这样一段代码不是很理解
百度了一下了解到分布式锁的概念
为什么需要锁
举个例子,假如在单机多线程环境下,多个线程需要访问同一个区域,我们需要控制这些线程按照顺序一个个执行 ,否则会出现并发问题,而上锁就是解决问题的方法之一。
锁的原理
设置一个各个线程都可以看见的标志,当有线程需要访问临界区域的时候,设置标志(Lock),这样其它线程就可以知道这里正在被使用。当访问结束的时候,取消标志(Unlock)。
keycenter中的分布式锁
keycenter用来处理token的签发等功能,需要使用redis。由于分布式的原因,同一时间只能有一个请求去修改数据库,否则可能出现同步问题。所以这里引入了分布式锁
keycenter中分布式锁的实现
keycenter使用redis来实现分布式锁。
12345678910111213// lockEntity 锁的实体// callback 上完锁的回调// gid 协程号idtype lockEntity struct { callback func() gid uint64}fu ...