Proto Plugin

1.插件命名规则 ​ proto插件名称需要使用protoc-gen-xxx ​ 当使用protoc –xxx_out时就会调用proto-gen-xxx插件 2.protobuf解析一般流程 方法1: 先通过标准输入生成CodeGeneratorRequest 通过CodeGeneratorRequest初始化插件plugin 通过插件plugin获取文件File 遍历文件,处理内容,生成文件 像标准输出写入响应plugin.Response 示例代码: s := flag.String("a", "", "a") flag.Parse() //生成Request input, _ := ioutil.ReadAll(os.Stdin) var req pluginpb.CodeGeneratorRequest proto.Unmarshal(input, &req) //设置参数,生成plugin opts := protogen.Options{ ParamFunc: flag.CommandLine.Set, } plugin, err := opts.New(&req) if err != nil { panic(err) } fmt.Fprintf(os.Stderr, "a=%s\n", *s) // protoc 将一组文件结构传递给程序处理,包含proto中import中的文件 for _, file := range plugin.Files { if !file.Generate { //显示传入的文件为true continue } fmt.Fprintf(os.Stderr, "path:%s\n", file.GoImportPath) genF := plugin.NewGeneratedFile(fmt.Sprintf("%s_error.pb.go", file.GeneratedFilenamePrefix), file.GoImportPath) //用来处理生成文件的对象 GenFile(genF, file, *s) } // 生成response resp := plugin.Response() out, err := proto.Marshal(resp) if err != nil { panic(err) } // 相应输出到stdout, 它将被 protoc 接收 fmt.Fprintf(os.Stdout, string(out)) 方法2: var s = flag.String("aaa", "", "aaa") var s1 = flag.String("bbb", "", "aaa") flag.Parse() protogen.Options{ ParamFunc: flag.CommandLine.Set, //设置命令行参数 --xxx_out=aaa=10,bbb=20:. }.Run(func(gen *protogen.Plugin) error { //Run内部封装了方法1的步骤 for _, f := range gen.Files { if !f.Generate { //判断是否需要生成代码, 影响这里是否是true的原因是protoc是否指定这个文件 continue } //遍历各种message/service...,同方法1 } }) 示例代码: ...

2022-10-19 11:39:19    |    3 分钟    |    518 字    |    Fengbin

树莓派安装k8s

本地系统为树莓派官方64位系统 Raspberry Pi OS Lite 64(Debian GNU/Linux 11) 在master和node都需要执行的步骤 本机cgroup配置 在执行kubeadm init 时出现 missing required cgroup: memory时,可以在/boot/cmdline.txt(有的系统可能在/boot/firmware/cmdline.txt)中追加 cgroup_enable=memory cgroup_memory=1 cgroup_enable=memory: 启用Cgroup子系统中的内存控制 cgroup_memory=1: 将内存控制子系统的版本设置为1 在某些特定的发行版中,可能会出于兼容性或其他原因而禁用了Cgroup子系统中的内存控制功能,所以需要手动开启 关闭swap 网上很多教程通过编辑/etc/fstab编辑swap, 但是在树莓派系统中,并不使用fstab配置,正确的做法是 编辑/etc/dphys-swapfile 找到配置项CONF_SWAPSIZE (通过名称我们可以知道该配置项为swap大小)该值配置为0 使配置生效 sudo /etc/init.d/dphys-swapfile restart 或者 sudo reboot 重启 通过free -h命令查看swap大小 系统模块加载 # 必要的模块加载 # overlay 文件系统 # br_netfilter 网桥网络包过滤 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF # 这个命令会将 "overlay" 和 "br_netfilter" 内核模块的名称添加到 /etc/modules-load.d/k8s.conf 文件中,以便在系统启动时自动加载这些模块 sudo modprobe overlay sudo modprobe br_netfilter # sudo modprobe overlay:加载 overlay 的内核模块,该模块提供了用于 overlayfs 的文件系统类型。在使用容器化技术如 Docker 时,通常需要使用 overlayfs 进行容器镜像的存储和管理。因此,在启用容器化环境时,需要确保该模块已加载。 # sudo modprobe br_netfilter:加载 br_netfilter 的内核模块,该模块提供了用于 Linux 桥接网络的过滤和 NAT 功能。在使用 Kubernetes 集群时,通常需要将容器内部的网络流量转发到主机上的网络设备,以实现容器与外部网络的通信。因此,在启用 Kubernetes 集群时,需要确保该模块已加载。 # 开启转发和流量可观测(开机启动) # sysctl params required by setup, params persist across reboots # bridge-nf-call-iptables 让ip表可以看到桥接流量 # bridge-nf-call-ip6tables 让ip6表可以看到桥接流量 cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF # 这个命令的作用是将其写入 /etc/sysctl.d/k8s.conf 文件中。在系统启动时,这些参数就会被自动设置。 # net.bridge.bridge-nf-call-iptables: 设置为 1,表示将 Linux 桥接网络中的 IP 数据包转发给 iptables 进行过滤。在使用 Kubernetes 时,需要启用此功能以实现网络策略等功能。 # net.bridge.bridge-nf-call-ip6tables: 设置为 1,表示将 Linux 桥接网络中的 IPv6 数据包转发给 ip6tables 进行过滤。 # net.ipv4.ip_forward: 设置为 1,表示启用 IPv4 数据包的转发功能。在使用 Kubernetes 时,需要启用此功能以实现跨节点的容器网络互通。 # Apply sysctl params without reboot(不用开机立刻生效) sudo sysctl --system CRI安装 根据官方文档配置环境doc ...

2022-10-05 20:49:13    |    3 分钟    |    525 字    |    Fengbin

树莓派系统关闭swap

网上很多教程通过编辑/etc/fstab编辑swap, 但是在树莓派系统中,并不使用fstab配置,正确的做法是 编辑/etc/dphys-swapfile 找到配置项CONF_SWAPSIZE (通过名称我们可以知道该配置项为swap大小)该值配置为0 使配置生效 sudo /etc/init.d/dphys-swapfile restart 或者 sudo reboot 重启 通过free -h命令查看swap大小

2022-10-02 21:10:36    |    1 分钟    |    15 字    |    Fengbin

Qemu+gdb裸机调试

假设我们有一个boot.bin裸机汇编程序 我们想用qemu进行调试 我们可以使用qemu-system-x86_64 -s -S boot.bin 参数说明: -s 可以使qemu开启1234端口,方便我们使用gdb连接调试 -S 可以让qemu暂停执行,等待我们使用gdb发送调试命令 gdb 连接: 使用gdb命令,进入gdb后使用target remote 127.0.0.1:1234连接到qemu

2022-09-23 16:31:24    |    1 分钟    |    16 字    |    Fengbin

errgroup

errgroup是一个很简单的工具包,总共代码量加上注释和空行才100来行 作用就是方便执行的任务,比如 g := errgroup.Group{} g.Go(func1) g.Go(func2) if err := g.Wait(); err != nil { //... } 结构 type Group struct { cancel func() //context 取消函数 wg sync.WaitGroup //用来等待全部执行完成 sem chan token //用来控制并发数 errOnce sync.Once //控制err字段只赋值一次 err error //错误 } 主要函数 func (g *Group) Go(f func() error) { if g.sem != nil { g.sem <- token{} //限制并发数, 并发数由管道能容纳下的token个数决定 } g.wg.Add(1) go func() { defer g.done() if err := f(); err != nil { g.errOnce.Do(func() { //如果出错后只赋值一次err g.err = err if g.cancel != nil { //如果使用的是WithContext,这个字段会有值, 调用取消函数 g.cancel() } }) } }() } 主要的东西就这么点, 可以看到errgroup还是一个很简洁的小工具, 配合singleflight一起使用挺不错

2022-09-06 17:22:20    |    1 分钟    |    95 字    |    Fengbin

AMQP 0-9-1协议

约定 下面出现的无特殊说明都是按下面对应关系 Publishers(发布者/生产者) Consumers(消费者) Exchanges(交换机) Broker(中间件) Queues(队列) Bingdings(绑定) AMQP是什么 AMQP是Advanced Message Queuing Protocol的缩写,高级消息队列协议,是一种消息传递协议 中间件和角色 消息中间件从Publishers(发布者/生产者)接收消息,路由到Consumers(消费者) 因为AMQP是网络协议, 发布者,消费者,中间件能够在不同的机器上. AMQP模型简介 AMQP模型有下面的视角: 消息被发布到交换机(exchange,通常被比作邮局或邮箱) 交换机(exchanges)根据绑定(bindings)规则把消息复制到队列(queues) 中间件(borker)把消息投递到订阅队列或者从队列中拉取的消费者(consumers) 当一个消息发布时, 生产者可以设置一些消息属性(消息元数据meta data).一些元数据被中间件使用,剩下其他的被不透明发送到中间件给应用程序使用. 网络是不可靠的,应用也有可能处理消息失败,AMQP 0-9-1有一个消息应答(acknowledgements)的概念:当一个消息派发给消费者,消费者会通知中间件,可以自动执行或者开发者选择执行.当使用消息确认时,收到消息的通知就会从队列里删除该消息. 在某些情况,比如一个消息无法被路由,消息将会返回给生产者,丢弃,或者如果中间件实现一个扩展放入死信队列.生产者通过发布消息携带某些参数来处理这些情况. 队列(queue)、交换机(exchanges)和绑定(bingdings)统称为AMQP实体. AMQP是一个可编程的协议 AMQP是一种可编程协议,AMQP的实体和路由方案主要由应用程序自己定义,而不是由中间件管理员定义.因此,为声明队列和交换机、定义它们之间的绑定、订阅队列等操作做出了规定. 这给应用程序开发者很大的自由,但是这也要求他们意识到潜在的定义冲突,在实践中定义冲突很少,通常是配置错误。 应用定义他们需要的实体,定义必要的路由规则和不在使用时删除实体 交换机和交换机类型 交换机是向其发送消息的AMQP实体,交换机接收消息并将其路由到零个或多个队列中。使用的路由算法取决于交换机类型和绑定,AMQP协议提供四种交换机类型: 交换机类型 默认名称 Direct exchange(直接交换机) (Empty string) and amq.direct Fanout exchange(扇出交换机) amq.fanout Topic exchange(主题交换机) amq.topic Headers exchange(头交换机) amq.match (and amq.headers in RabbitMQ) 除了交换机类型之外,交换机还使用许多属性来声明,其中最重要的是: Name (名称) Durability (中间件重启后持久化) Auto-delete (最后一个队列解除绑定自动删除) Arguments (参数,可选的, 由插件和中间件特定功能使用) 交换机可以是持久的或者是临时的,持久性交换机在中间件重启后仍能存在,而暂时性交换机则不能.并非所有场景和用例都要求交换机持久化. 默认交换机 默认交换机是一个没有名称预定义在broker的直接交换机(direct exchange),它有一个特殊的特性,这使得它对于简单的应用程序非常有用:每个被创建的队列都会用和队列名称相同的路由键(routing key)自动绑定默认交换机. ...

2022-08-02 11:06:49    |    1 分钟    |    98 字    |    Fengbin

Fisher-Yates Shuffle

这个算法发是今天看了一个go的代码库看到的,通过lo库看到有个Shuffle函数点进去看了一下,调用的数标准库中的shuffle算法,看了一下介绍,感觉有点意思,记录一下 Fisher-Yates算法是什么 Fisher-Yates算法 是一种生成随机排列的算法 核心原理 — To shuffle an array ‘a’ of ‘n’ elements: //对于一个规模为n的集合 for i from n-1 down to 1 do //从后向前遍历 j = random integer such that 0 <= j <= i //随机一个从0-i数字 exchange a[j] and a[i] //交换随机下标和当前下标的元素交换 用语言描述就是: 从后向前遍历 随机一个下标范围是0到当前下标,(范围包含当前下标是因为可能不交换) 交换随机下标指向的值和当前下标指向的值 go语言描述 func init(){ rand.Seed(time.Now().Unix()) } func Shuffle[T any](t []T) { for i := len(t) - 1; i > 0; i-- { j := rand.Int() % (i + 1) t[i], t[j] = t[j], t[i] } }

2022-07-27 11:41:33    |    1 分钟    |    80 字    |    Fengbin

语法图

语法图又称铁路图,是EBNF(扩展巴克斯范式)的图形化表示 从左边界开始沿着轨道去到右边界。 沿途,你将在圆框中遇到的是字面量,在方块中遇到的是规则或者描述。 任何沿着轨道能走通的序列都是合法的。 任何不能沿着轨道走通的序列都是非法的。 /* a simple program in EBNF − Wikipedia */ program ::= 'PROGRAM' whiteSpace identifier whiteSpace 'BEGIN' whiteSpace (assignment ";")* 'END.' assignment ::= identifier ":=" ( number | identifier | string ) string ::= '"' [A-Z0-9_]+ '"' identifier ::= [A-Z] [0-9A-Z]* whiteSpace ::= [#x20]

2022-07-07 18:00:27    |    1 分钟    |    48 字    |    Fengbin

EBNF

EBNF 扩展巴科斯-瑙尔范式(EBNF, Extended Backus–Naur Form) 是表达作为描述计算机编程语言形式语言(是用精确的数学或机器可处理的公式定义的语言) 的正规方式的上下文无关文法 的元语法(metalanguage)符号表示法。它是巴科斯范式(BNF) 元语法符号表示法的一种扩展。 简单的理解就是用来描述语言词法和语法规则的语言 ISO/IEC 14977标准 基本形式 LEFT=RIGHT 意思为LEFT可由RIGHT推导而来,LEFT为非终结符,RIGHT可以为非终结符也可以为终结符; 非终结符 简单的理解就是可以继续推导的符号 终结符 不可被推导的符号 符号 符号 含义 示例 = 定义 CharA=“a”; 代表CharA由字母a推导而来 , 连接符 a,b,c 代表abc是挨着的 ; 结束符 CharA=“a”; 代表 CharA这条语句定义结束 | 或者 digit = “0” | “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9”; […] 可选,出现0次或1次 number = ["-"|"+"],digit 可匹配 1 -1 +1 … {…} 重复,出现>=0次 number = ["-"|"+"],digit,{digit} 可匹配 1 -1 +1 11 … (…) 分组 number = ("-"|"+"),digit 符号必须添加,可匹配 -1 +1 … “…“或者’…' 终结符,单引号主要是一些特殊情况,比如双引号 “a"或者’a’ 由单或双引号引起来的部分是终结符,就是代表字母a,不可继续推导 (* … *) 注释 (*我是注释*) 注释不参与定义 ?…? 表示其中的内容具有特殊含义,对该含义的定义不在 EBNF 标准之内,有使用者来决定 space = ? US-ASCII character 32 ?; - 排除(将右边的内容从左边进行排除) string= allVistableChar - '”’ 表示在allVistableChar里排除"字符 示例 只允许赋值的简单编程语言可以用 EBNF ...

2022-07-05 15:31:12    |    3 分钟    |    430 字    |    Fengbin

计算机网络简要概述

计算机网络分层 市面上对网络分层主要是有三种分层 七层 五层 四层 应用层 应用层 应用层 表示层 会话层 传输层 传输层 传输层 网络层 网络层 网络层 数据链路层 数据链路层 网络接口层 物理层 物理层 每层的职责 物理层 提供物理介质,电压信号等功能 数据链路层 提供P2P传输 (点对点的, 比如一个路由器到另一个路由器) 网络层 提供E2E传输 (Endpoint to Endpoint,两个端点的传输,中间可能经过若干个路由器,注意区别P2P, E2E > P2P) 传输控制层 提供进程到进程的传输(端口到端口的传输) 应用层 应用自定义个协议 每一层都是通过下层对上层提供接口的形式来提供服务 常用网络设备 交换机 交换机工作在数据链路层, 通过mac地址进行转发, 全双工网络设备, 可以隔离碰撞域, 减少链路上的信号碰撞,提高链路网络利用率 路由器 路由器工作在网际层, 通过ip进行转发, 全双工网络设备, 可以隔离广播域(广播不能通过路由器)

2022-07-04 21:10:39    |    1 分钟    |    53 字    |    Fengbin