Go语言实现简易版netstat命令

netstat工作原理

netstat命令是linux系统中查看网络情况的一个命令。比如我们可以通过netstat -ntlp | grep 8080查看监听8080端口的进程。

netstat工作原理如下:

  1. 通过读取/proc/net/tcp 、/proc/net/tcp6文件,获取socket本地地址,本地端口,远程地址,远程端口,状态,inode等信息
  2. 接着扫描所有/proc/[pid]/fd目录下的的socket文件描述符,建立inode到进程pid映射
  3. 根据pid读取/proc/[pid]/cmdline文件,获取进程命令和启动参数
  4. 根据2,3步骤,即可以获得1中对应socket的相关进程信息

Read More

多网卡模式下Golang应用的流量从指定网卡流入流出方案

最近因业务需要,需要在多网卡模式下实现Go应用的流量从指定网卡流入,请求外网服务时候流量需要从该网卡流出功能。从指定网卡流入很容易实现,只要go应用listen对应网卡即可,但请求外网服务时候就相对麻烦些了。在实践中总结出有三种方案可行。各有优劣。

假定服务器网卡情况如下:

网卡 网卡IP 对应的公网IP
eth0 172.31.0.8 109.25.48.65
eth1 172.31.0.14 119.26.38.75

实际上我们的服务器使用云服务器,网卡是弹性网卡(eni),绑定的是弹性ip(eip)。三种方案对普通服务器也是能达到目的的。

Read More

Golang源码分析系列之Channel底层实现

Golang中Channel是goroutine间重要通信的方式,是并发安全的,通道内的数据First In First Out,我们可以把通道想象成队列。这里面分析的源码基于go1.13版本。

channel数据结构

Channel底层数据结构是一个结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
type hchan struct {
qcount uint // 队列中元素个数
dataqsiz uint // 循环队列的大小
buf unsafe.Pointer // 指向循环队列
elemsize uint16 // 通道里面的元素大小
closed uint32 // 通道关闭的标志
elemtype *_type // 通道元素的类型
sendx uint // 待发送的索引,即循环队列中的队尾指针front
recvx uint // 待读取的索引,即循环队列中的队头指针rear
recvq waitq // 接收等待队列
sendq waitq // 发送等待队列
lock mutex // 互斥锁
}

Read More

Elasticsearch内存占用分析与管理

Elasticsearch是基于JVM实现的,内存分配分为堆内(on-heap)和堆外(off-heapp)两部分。每部分的内存,可以用于不同目的的缓存,具体可以看下思维导图:

从整体来看如下所示:

堆内存与堆外内存

一般情况下,Java中分配的非空对象都是由Java虚拟机的垃圾收集器管理的,称为堆内内存(on-heap memory)。虚拟机会定期对垃圾内存进行回收,在某些特定的时间点,它会进行一次彻底的回收(full gc)。彻底回收时,垃圾收集器会对所有分配的堆内内存进行完整的扫描,这意味着一个重要的事实——这样一次垃圾收集对Java应用造成的影响,跟堆的大小是成正比的。过大的堆会影响Java应用的性能。

Java虚拟机的堆以外的内存,即直接收操作系统管理的内存属于堆外内存(off-heap memory),通过把内存对象分配在堆外内存中,可以保持一个较小的堆,可以减少垃圾回收对应用的影响。

Read More

Golang中信号处理

什么是信号?

信号(signal)是进程间通讯的一种方式,用来提醒进程某个事件已经发生。它属于一种异步通知进制。一个进程不必通过任何操作来等待信号的到达,事实上进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。

Read More

Golang并发调度的GMP模型

Golang的一大特色就是Goroutine。Goroutine是Golang支持高并发的重要保障。Golang可以创建成千上万个Goroutine来处理任务,将这些Goroutine分配、负载、调度到处理器上采用的是G-M-P模型。

什么是Goroutine

Goroutine = Golang + Coroutine。Goroutine是golang实现的协程,是用户级线程。Goroutine具有以下特点:

  • 相比线程,其启动的代价很小,以很小栈空间启动(2Kb左右)
  • 能够动态地伸缩栈的大小,最大可以支持到Gb级别
  • 工作在用户态,切换成很小
  • 与线程关系是n:m,即可以在n个系统线程上多工调度m个Goroutine

Read More

Golang源码分析系列之官方Context包

Context简介

Context是由Golang官方开发的并发控制包,一方面可以用于当请求超时或者取消时候,相关的goroutine马上退出释放资源,另一方面Context本身含义就是上下文,其可以在多个goroutine或者多个处理函数之间传递共享的信息。

创建一个新的context,必须基于一个父context,新的context又可以作为其他context的父context。所有context在一起构造成一个context树。

context tree

Read More

Golang设计模式系列之工厂方法模式

定义

工厂方法模式(Factory Method Pattern)也称为工厂模式(Factory Pattern)。同简单工厂模式一样,工厂方法模式也是一种创建型设计模式。不同于简单工厂模式的都是通过同一个具体类(类的静态方法)或者函数来创建对象,工厂方法模式是通过一系列实现创建对象接口的具体子类来创建对象。即:

工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。

Read More

Raft:一种分布式一致性算法

什么是分布式一致性

分布式一致性(Distributed Consensus)简单来说就是在多个节点组成系统中各个节点的数据保持一致,并且可以承受某些节点数据不一致或操作失败造成的影响。分布式一致性是分布式系统的基石。

Read More