Technology

Ubuntu BBR 加速

BBR是google的TCP阻塞控制算法,可以最大程度的利用带宽,提升网络传输速率。 Linux kernel 4.9 及以上已支持 tcp_bbr 1.查看系统内核版本: uname -r 看内核版本是否大于等于4.9,否则要升级内核,或者安装bbr。 2.开启BBR: echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf 3.保存生效: sysctl -p 4.检查BBR是否启用: [root@linux ~] sysctl net.ipv4.tcp_available_congestion_control net.ipv4.tcp_available_congestion_control = reno cubic bbr [root@linux ~] sysctl net.

Mar 13, 2021

Shell输出重定向

操作符合 说明 < , « 标准输入重定向 >, », 1> , 1» 标准输出重定向 2> , 2» 标准错误重定向 &> 标准输出/错误重定向 m >& n 将m的输出合并到n m <& n 将n的输输入合并到m >:重定向 >>:重定向追加

Dec 11, 2020

如何让Gitlab私有仓库支持Go Get

通常公司都会有自己的Git仓库,可能涉及到利用go get进行项目依赖的问题。 我们以Gitlab作为私有仓库为例,仓库地址为:gitlab.com。 私有仓库鉴权设置 go get默认采用的https下载项目依赖,而私有仓库一般采用的ssh key的方式鉴权,所以直接使用go get会出现https鉴权失败的问题,解决办法有两种。 1. 将https替换为ssh 这种方式适合在自己的电脑上使用。 让git执行 git clone https://gitlab.com/xx.git时,自动替换为执行git clone git@gitlab.etsus.net:xx.git,需要执行如下命令: git config --global url."git@gitlab.etsus.net:".insteadof "https://gitlab.etsus.net/" 2. 利用Gitlab 的 Access Token鉴权 在有些情况下,比如对于编译服务器,可能采用ssh key的方式权限太大,可以采用Access Token的方式来解决问题。

Nov 5, 2020

Golang 编译约束/条件编译

通常对程序进行编译的时候,可能带一些条件(如不同平台、架构有不同的代码实现),让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。golang中,称之为编译约束,进行编译约束的方式有2种分别: 编译标签(build tag) 文件后缀 编译标签 (build tag) 在源码文件顶部添加注释,来决定文件是否参与编译 // +build <tags> <tags>说明: 以空格分开表示AND 以逗号分开表示OR !表示NOT 标签可以指定为以下内容: 操作系统,环境变量中GOOS的值,如:linux、darwin、windows等等。 操作系统的架构,环境变量中GOARCH的值,如:arch64、x86、i386等等。 使用的编译器,gc或者gccgo。 是否开启CGO,cgo。 golang版本号: 比如Go Version 1.1为go1.1,Go Version 1.12版本为go1.12,以此类推。 其它自定义标签,通过go build -tags指定的值。 例如,编译条件为(linux AND 386) OR (darwin AND (NOT cgo))

Nov 4, 2020

Golang GC 三色标记

v1.3以前:STW 在Go语言1.3之前,Go的垃圾回收过程采用了一个称为STW(Stop-The-World)的方法。这意味着在进行垃圾回收时,所有的Go协程都会被停止,直到垃圾回收完成。这种方式可能会导致程序在垃圾回收期间出现短暂的停顿,影响了程序的响应性能。 垃圾回收的过程主要包括以下几个步骤: 标记(Marking):从根对象(如全局变量、活动栈、寄存器等)开始,通过一种深度优先搜索算法,标记所有可以访问到的对象为活动对象(live objects)。 清扫(Sweeping):遍历堆内存,将未被标记的对象回收,释放它们所占用的内存。 压缩(Compaction):对堆内存进行压缩,使得已回收的内存空间连续起来,以便后续的内存分配能够更加高效。 这个垃圾回收过程在1.3版本之前主要是通过暂停整个应用程序来执行的,因此在大型应用程序中可能会导致较长的停顿时间,对于对实时性要求较高的应用程序可能会有影响。 v1.3:Mark STW & Sweep 1.3版本中,go runtime分离了mark和sweep操作,和以前一样,也是先暂停所有任务执行并启动mark,mark完成后马上就重新启动被暂停的任务了,而是让sweep任务和普通协程任务一样并行的和其他任务一起执行。如果运行在多核处理器上,go会试图将gc任务放到单独的核心上运行而尽量不影响业务代码的执行。go team自己的说法是减少了50%-70%的暂停时间。 v1.5:三色标记算法 三色标记算法(也称为Tri-Color Marking Algorithm)是一种用于垃圾回收的算法,通常用于实现并发标记-清除垃圾回收器。该算法通过将对象标记为三种颜色(通常是白色、灰色和黑色)来跟踪对象的可达性,并在标记过程中处理引用的变化。 它将对象分为三种颜色表示,分别是白色、灰色和黑色。 白色(White):表示对象尚未被访问或标记。在初始标记之前,所有的对象通常都是白色的。在初始标记后,白色对象可能被标记为灰色或黑色。 灰色(Gray):表示对象已经被发现,但其引用的其他对象尚未被遍历。换句话说,灰色对象的引用链路尚未完全探索。在追踪阶段,会从灰色对象开始继续探索其引用的其他对象,并将这些对象标记为灰色。一旦所有引用的对象都被遍历,灰色对象就会被标记为黑色。 黑色(Black):表示对象已经被完全探索,即其引用的所有其他对象都已经被遍历过,并且它们的可达性已经确定。黑色对象是被保证是可达的,不会被垃圾回收器回收。一旦对象变为黑色,它就会保持这种状态,直到下一次垃圾回收过程。 初始化: 算法开始前,将所有的对象标记为白色(表示未访问)。 根节点标记: 从程序的根节点开始,例如全局变量、活跃线程的栈、寄存器等,将这些根节点指向的对象标记为灰色(表示待访问)。 标记阶段: 不断地从灰色对象集合中取出一个对象进行标记,然后遍历该对象引用的其他对象。对于每个被引用的对象: 如果该对象是白色的,则将其标记为灰色,并将其加入灰色对象集合。 如果该对象已经是灰色或黑色的,则不需要做任何操作。 标记结束: 当灰色对象集合为空时,标记阶段结束。 清除阶段: 遍历所有对象,将未标记的对象(即白色的对象)视为垃圾,进行回收或其他处理。同时,将所有标记为灰色的对象重新标记为黑色(表示已访问)。 结束: 清除阶段完成后,垃圾回收器的工作完成,可以继续应用程序的执行。 三色标记算法(Three-color marking algorithm)通常用于垃圾回收(Garbage Collection)中,特别是在分代垃圾回收中。该算法使用三种不同的颜色来标记内存中的对象,以区分它们的状态。通常情况下,这三种颜色是白色(White)、灰色(Gray)和黑色(Black)。以下是三色标记算法的一般步骤:

Nov 4, 2020

Git 删除子模块/远程分支

删除子模块 # 逆初始化模块,其中{MOD_NAME}为模块目录,执行后可发现模块目录被清空 git submodule deinit {MOD_NAME} # 删除.gitmodules中记录的模块信息(--cached选项清除.git/modules中的缓存) git rm --cached {MOD_NAME} # 提交更改到代码库,可观察到'.gitmodules'内容发生变更 git commit -am "Remove a submodule." 修改某模块URL 修改’.gitmodules’文件中对应模块的”url“属性; 使用git submodule sync命令,将新的URL更新到文件.git/config; $ git submodule sync # 运行后可观察到'.

Nov 3, 2020

通过Github自动部署Hugo

以前通过hexo 和 dukewiki 做过个人学习笔记和Blog,但是部署在树莓派上。因为该死的switch,对,就是玩游戏的那个。当时switch有SD不够用,就把树莓派上的SD卡拿来格式化了(忘记wiki部署在上面),结果所有的笔记全部没有了。这是一个悲惨的教训,所以有了接下来的事情,废话不多说了,直接开始。

Nov 2, 2020

Volatile 关键词

volatile适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。 正常情况下: 有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈。 当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程私有内存中(线程栈),建立一个变量副本 之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值。 在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。 volatile变量改变后写回主内存时,会让所有线程的工程内存中该变量副本置为无效,那么其他线程再次读取变量副本时由于副本时无效的会从主内存中重新读取,从而达到读取到最新值的效果 volatile适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。 值得说明的是对volatile变量的单次读/写操作可以保证原子性的,如long和double类型变量,但是并不能保证i++这种操作的原子性,因为本质上i++是读、写两次操作。 public class VolatileTest extends Thread { boolean flag = false; int i = 0; public void run() { while (!flag) { i++; } } public static void main(String[] args) throws Exception { VolatileTest vt = new VolatileTest(); vt.

Nov 2, 2020

NIO

在讲NIO的原理之前,首先掌握几个基础概念,内核缓冲进程缓冲区 进程缓冲区:存在于用户程序空间,由应用程序进行管理。 内核缓冲区:存在于内核空间,由操作系统的内核进行管理,当我们进行IO操作的时候,无论是硬盘还是网络,内核缓冲去的数据什么时候写入到磁盘,什么时候写入到网卡,是由内核来决定,应用程序不需要感知。 四种主要的IO模型 什么是阻塞和非阻塞? 阻塞和非阻塞是针对于进程在访问数据时,根据IO操作的就绪状态而采取的不同方式,简单来说是一种读取或写入操作函数的实现方式,阻塞方式下读取或写入函数将一直等待。非阻塞方式下,读取和写入函数会立即返回一个状态值。 什么是同步和异步? 同步和异步是针对应用程序和内核的交互而言的,同步是指用户进程触发IO操作并等待或轮询的查看IO操作是否就绪,异步是指用户进程触发IO操作以后便开始做自己的事情,当IO操作完成时会得到通知,换句话说异步的特点就是通知。 IO模型可以分为四种:同步阻塞、同步非阻塞、异步阻塞、异步非阻塞 同步阻塞IO(Blocking IO) 阻塞IO,指的是需要内核IO操作彻底完成后,才返回到用户空间,执行用户的操作。阻塞指的是用户空间程序的执行状态,用户空间程序需等到IO操作彻底完成。传统的IO模型都是同步阻塞IO,其中同步是指用户应用程序主动向内核发起IO请求。 同步非阻塞IO(Non-blocking IO) 非阻塞IO,指的是用户程序不需要等待内核IO操作完成后,内核立即返回给用户一个状态值,用户空间无需等到内核的IO操作彻底完成,可以立即返回用户空间,执行用户的操作,处于非阻塞的状态。 异步阻塞(Asynchronous Blocking IO) 异步IO,指的是用户空间与内核空间的调用方式反过来。用户空间线程是变成被动接受的,内核空间是主动调用者。 同步阻塞IO是指用户进程在发起一个IO操作后必须等待IO操作完成,只有当真正完成了IO操作后用户进程才能运行。 同步非阻塞IO是指用户进程发起一个IO操作后立即返回,程序也就可以做其他事情。但是用户进程需要不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。 NIO NIO是同步非阻塞IO 同步是进行IO操作的时候是由应用程序主动发起向内核发起IO请求。 非阻塞表示IO操作不会阻塞当前进程的执行。 如果和避免NIO中的论 NIO采用了IO多路复用技术,因为NIO是同步IO,所以采用的是多路复用中的Reactor模式。 NIO的select实际上是使用的epoll来实现的,EPollSelectorImpl extend SelectorImpl。

Nov 2, 2020

MySQL授权

创建数据库 create database <database> default character set utf8mb4 collate utf8mb4_unicode_ci; 参数说明: <database>: 数据库名称 用户管理 添加用户 create user '<username>'@'<host>' identified by '<password>' 例子: create user 'xiaoming'@'localhost' identified by '123'; create user 'xiaoming'@'192.

Nov 2, 2020