恭喜 👏👏👏 大谷はメジャー 7 年目、移籍 1 年目で初の世界一。山本由伸投手(26)もメジャー 1 年目で栄冠を手にした。
棒球确实是一项很棒的团队运动,虽然大谷常规赛很出色,但是在世界大赛中的表现并不好(法官同样哑火,好在后面轰了一发),但他拥有很棒的队友。「自由人」Freddie Freeman 绝对是世界大赛 MVP、世界大赛连续 4 场开轰、跨季世界大賽连续六场全垒打。九局下半,少主 Walker Buehler 关门成功。
感谢所有美国职业棒球大联盟球员在过去一年的奉献。
1// findSmallestMissingNumber 查找数组中缺失的最小正整数 2func findSmallestMissingNumber(nums []int) int { 3 n := len(nums) 4 5 // 遍历数组,将每个数字放到它应该在的位置上 6 for i := 0; i < n; i++ { 7 for nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i] { 8 nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i] 9 } 10 } 11 12 // 再次遍历数组,找到第一个不在正确位置上的数字 13 for i := 0; i < n; i++ { 14 if nums[i] != i + 1 { 15 return i + 1 16 } 17 } 18 19 // 如果数组中的数字是从 1 到 n 的连续数字,则最小的缺失数字是 n+1 20 return n + 1 21}
1// UndistortImage 畸变校正 2func UndistortImage(imgData []byte, imgSize image.Point, cameraMatrix gocv.Mat, distCoeffs gocv.Mat, newCameraMatrix gocv.Mat) ([]byte, error) { 3 mapx := gocv.NewMatWithSize(imgSize.X, imgSize.Y, gocv.MatTypeCV32F) 4 defer mapx.Close() 5 mapy := gocv.NewMatWithSize(imgSize.X, imgSize.Y, gocv.MatTypeCV32F) 6 defer mapy.Close() 7 r := gocv.Eye(3, 3, gocv.MatTypeCV32F) 8 defer r.Close() 9 10 // 初始化校正映射 11 gocv.InitUndistortRectifyMap(cameraMatrix, distCoeffs, r, newCameraMatrix, imgSize, int(gocv.MatTypeCV32F), mapx, mapy) 12 // 保存校正后图像 13 src, err := gocv.IMDecode(imgData, gocv.IMReadGrayScale) 14 if err !
...
1// CalibCamera 标定相机 2func CalibCamera(imgDatas [][]byte, chessboardRowCornerCount int, chessboardColCornerCount int, curImageIndex int) error { 3 // 保存各图像中的角点的二维坐标, 即像素坐标 4 imgPoints := gocv.NewPoints2fVector() 5 defer imgPoints.Close() 6 // 保存各图像中的角点的三维坐标,即世界坐标 7 objPoints := gocv.NewPoints3fVector() 8 defer objPoints.Close() 9 // 保存图片尺寸 10 imgSize := image.Point{X: 0, Y: 0} 11 12 // 为三维点定义世界坐标系 13 objectPoints := make([]gocv.Point3f, 0) 14 for i := 0; i < chessboardColCornerCount; i++ { 15 for j := 0; j < chessboardRowCornerCount; j++ { 16 objectPoints = append(objectPoints, gocv.
...
1. 最小二乘法 推导过程可参考 Kåsa Fit 算法:
1// fitCenterByLeastSquare 最小二乘法拟合圆 2func fitCenterByLeastSquare(points []gocv.Point2f) (gocv.Point2f, float32) { 3 var sumX, sumY, sumX2, sumY2, sumXY, sumX3, sumY3, sumX2Y, sumY2X float32 4 for _, p := range points { 5 sumX += p.X 6 sumY += p.Y 7 sumX2 += p.X * p.X 8 sumY2 += p.Y * p.Y 9 sumXY += p.X * p.Y 10 sumX3 += p.X * p.X * p.X 11 sumY3 += p.
...
场景 当 Yaml 作为配置文件时候,往往在启动服务的时候就需要解析配置,如果修改了某个字段的数据结构,开局就 panic,有时候我们并不希望此时就停止业务,希望能用默认的配置文件替代。
1# cfg.yaml 2language: Golang 3animal: Dog 1type Cfg struct { 2 Language string `json:"language,omitempty"` 3 Animal string `json:"animal,omitempty"` 4} 正常情况下,Yaml 文件会被解析成功,如下:
1package main 2 3import ( 4 "fmt" 5 "os" 6 7 "github.com/goccy/go-yaml" 8) 9 10type Cfg struct { 11 Language string `json:"language,omitempty"` 12 Animal string `json:"animal,omitempty"` 13} 14 15func main() { 16 CfgPath := "C:\\Users\\han1en9\\Desktop\\Project\\Demo\\cfg.yaml" 17 18 var cfg Cfg 19 b, _ := os.
...
kill 1$ kill pid # kill -15 pid 默认的 kill 系统会发送一个 SIGTERM 的信号给对应的程序,当程序接收到该 signal 后:
程序立刻停止 当程序释放相应资源后再停止 程序可能仍然继续运行 大部分程序接收到 SIGTERM 信号后,会先释放自己的资源,然后在停止。但是也有程序可以在接受到信号量后,做一些其他的事情,并且这些事情是可以配置的。如果程序正在等待 IO,可能就不会立马做出相应。也就是说,SIGTERM 多半是会被阻塞的、忽略。
kill -15 信号只是通知对应的进程要进行"安全、干净的退出",程序接到信号之后,退出前一般会进行一些"准备工作",如资源释放、临时文件清理等等,如果准备工作做完了,再进行程序的终止。如果在"准备工作"进行过程中,遇到阻塞或者其他问题导致无法成功,那么应用程序可以选择忽略该终止信号。
1$ kill -9 pid 必杀,强制删除。在执行时,应用程序是没有时间进行"准备工作"的,所以这通常会带来一些副作用,数据丢失或者终端无法恢复到正常状态等。
ps Linux ps (英文全拼:process status)命令用于显示当前进程的状态,类似于 windows 的任务管理器。.
1$ ps -ef | grep 进程关键字 # 查找指定进程 1# ps -ef | grep php 2root 794 1 0 2020 ? 00:00:52 php-fpm: master process (/etc/php/7.3/fpm/php-fpm.conf) 3www-data 951 794 0 2020 ? 00:24:15 php-fpm: pool www 4www-data 953 794 0 2020 ?
...
OVS 网络架构 Open vswitch 是一个开放的虚拟交换机,支持 openflow 协议,被远端的控制器通过 openflow 协议统一管理,从而实现对接入的虚拟机或设备进行组网和互通,主要作用就是:
传递虚拟机之间的流量 实现虚拟机和外界网络之间的通信 OVS 内部结构 OVS 有三个核心的部分:
ovs-vswitchd: 实现 OVS 守护进程 daemon,OVS 的核心部件,实现交换功能,和 Linux 内核兼容模块一起,实现基于流的交换(flow-based switching)。它和上层 controller 通信遵从 OPENFLOW 协议,它与 ovsdb-server 通信使用 OVSDB 协议,它和内核模块通过 netlink 通信,它支持多个独立的 datapath(网桥),它通过更改 flow table 实现了绑定和 VLAN 等功能。 ovsdb-server: 轻量级的数据库服务,主要保存了整个 OVS 的配置信息,包括 port、交换内容、VLAN 等。ovs-vswitchd 会根据数据库中的配置信息工作。它于 manager 和 ovs-vswitchd 交换信息使用了 OVSDB(JSON-RPC) 的方式。 ovs kernal module(datapath + flowtable): 内核模块,负责执行数据处理,把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。处理包交换和隧道,缓存 flow,如果在内核的缓存中找到转发规则则转发,否则发向用户空间去处理。一个 datapath 可以对应多个 vport,一个 vport 类似物理交换机的端口概念。每一个 ovs 网桥(交换机)都有一个内核空间的 datapath 与之相对应,可以说这个 datapath 就是 ovs 网桥(交换机)的实体,数据流都是受它控制,而它是根据 flow table 。每一个 datapth 在内核中都关联一个 flow table,一个 flow table 包含多个条目,每个条目包括两个内容:一个 match/key 和一个 action。 为了方便配置和管理,所以有了下面的工具:
...
通俗理解 控制面是为了找好路径,转发面是在有个好路径的基础上转发数据,两者协作来达到网络是通的这样一个目的。
数据包是以跳为单位进行路由的,转发的决定是由接收到该数据包的路由器决定的。
The Control Plane: 决定怎么和从哪转发出去。
The Data Plane: 在路由器端口上进行实际包转发到线路上(硬件层面)。
官方定义 控制层面 :负责路由协议的更新和交互,路由的计算等。
通过控制和管理各协议的运行使得路由器或交换机能够对整个网络的设备、链路和运行的协议有一个准确的了解,并在网络发生变化时也能及时感知并调整。
转发层面 :负责IP数据报文的转发。
转发平面是用来进行数据的接收、解封装、封装、查找路由表进行转发数据。
控制层面和转发层面的分离
良好的系统设计应该是使控制平面与转发平面尽量分离,互不影响。 当系统的控制平面暂时出现故障时,转发平面还可以继续工作,这样可以保证网络中原有的业务不受系统故障的影响从而提高整个网络的可靠性。
在计算机网络中,路由器的主要工作就是为经过路由器的每个数据包寻找一条最佳的传输路径,并将该数据有效地传送到目的站点。在每一个路由器设备中,通常都维护了两张比较相似的表,分别为:
路由信息表(Routing Information Base),简称为RIB表、路由表 转发信息表(Forwarding Information Base), 简称为FIB表、转发表 其中,路由表(RIB表)用来决策路由;转发表用来转发分组。
路由器的核心工作便是为经过路由器的每一个数据包找到最佳路径(最快、质量最好、路径最短等指标选择最优),并将到达不同网络的最优路径对应的路由组成一张新的表格,即FIB表。
Destination:目的网络地址、Gatewat:网关、Genmask:子网掩码、Metric:跳数、Ref:引用次数、Use:查询次数
在进行报文转发(发送)时:
先查询路由表,确定目的地址是否可达,如果可达则确定出接口和下一跳信息 再查询ARP表,获取到目的地址对应的Mac地址信息,构建完整的以太网报文。 最后查询Mac表,是为了确定报文的发送接口,确定了出接口,内核会将报文发送到对应的网卡驱动上,网卡在合适的时间会将报文发送到下一跳设备上。