maven 依赖处理 用于依赖冲突 公司本身对某个jar做了特殊处理.例如修改了spring的源码.需要特殊指定. 使用的项目 : Building an Application with Spring Boot 指定依赖版本 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!– 排除依赖spring-core –> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> </exclusions> </dependency> <!– specify spring-core version –> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.1.0.RELEASE</version> </dependency>
Category: virtualization
虚拟化技术
linux 进程
进程 根据维基百科的定义,进程(Process)是计算机中已运行程序的实体。用户下达运行程序的命令后,就会产生进程。进程需要一些资源才能完成工作,如CPU使用时间、存储器、文件以及I/O设备,并且依序逐一进行.也就是每个CPU核心任何时间内仅能运行一项进程。 PID=1 有一个PID为1的进程是由内核创建的init进程,其他子进程都是由它衍生出来,进程号为1的进程并没有PPID 创建 操作系统通过POSIX定义的fork和exec接口创建起一个POSIX进程,这个进程就可以使用通用的IPC、信号等机制。 原来普通进程运行时默认会绑定TTY(虚拟终端),关闭终端后系统会给上面所有进程发送TERM信号,这时普通进程也就退出了。当然还有些进程不会退出,这就是后面将会提到的守护进程。 Nohup 的原理也很简单,终端关闭后会给此终端下的每一个进程发送SIGHUP信号,而使用nohup运行的进程则会忽略这个信号,因此终端关闭后进程也不会退出。 IPC全称Interprocess Communication,指进程间协作的各种方法,当然包括共享内存,信号量或Socket等。 FD 每个进程操作系统都会分配三个文件资源,分别是标准输入(STDIN)、标准输出(STDOUT)和错误输出(STDERR)。 Linux中“一切皆文件”,进程的一切运行信息(占用CPU、内存等)都可以在文件系统找到 go run 通过 go run 每次都会启动一个新的Go虚拟机来执行进程。 因为 go run 会启动进程重新编译、链接和运行程序,因此每次运行的进程名都不相同,而编译出来的程序有明确的名字, 进程锁 其实要实现一个进程锁很简单,通过文件就可以实现了。例如程序开始运行时去检查一个PID文件,如果文件存在就直接退出,如果文件不存在就创建一个,并把当前进程的PID写入文件中。 特殊的进程 孤儿进程 根据维基百科的解释,孤儿进程指的是在其父进程执行完成或被终止后仍继续运行的一类进程。 在现实中用户可能刻意使进程成为孤儿进程,这样就可以让它与父进程会话脱钩,成为后面会介绍的守护进程。 僵死进程 一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。 进程间通信 管道(Pipe) 管道是进程间通信最简单的方式,任何进程的标准输出都可以作为其他进程的输入。 信号(Signal) 信号Signal,注意信号只是告诉进程发生了什么事件,而不会传递任何数据。 消息队列(Message) 和传统消息队列类似,但是在内核实现的。 共享内存(Shared Memory) 信号量(Semaphore) 信号量本质上是一个整型计数器,调用wait时计数减一,减到零开始阻塞进程,从而达到进程、线程间协作的作用。 套接口(Socket) 通过网络来通信,这也是最通用的IPC,不要求进程在同一台服务器上。 信号 进程发给进程,也可以是内核发给进程 kill -l # HUP INT QUIT ILL TRAP… Continue reading linux 进程
香港阿里云ip路由
深圳阿里云到香港阿里云 要经过美国线路… 香港阿里云到深圳阿里云 看起来像走的内网到浙江阿里云 深圳阿里云到香港阿里云 [root@xxxxx ~]# traceroute 47.52.xx.xx traceroute to 47.52.xx.xx (47.52.xx.xx), 30 hops max, 60 byte packets 1 * * * 2 11.219.126.105 (11.219.126.105) 6.572 ms 11.219.127.109 (11.219.127.109) 6.830 ms 11.219.126.105 (11.219.126.105) 6.833 ms (美国) 3 11.219.127.154 (11.219.127.154) 5.981 ms 11.219.127.146 (11.219.127.146) 5.663 ms 11.219.126.154 (11.219.126.154) 5.612 ms 4 11.177.232.122 (11.177.232.122) 1.963 ms… Continue reading 香港阿里云ip路由
项目的jvm内存分析
项目的jvm内存分析 我们的项目是一个 java 写的高重删多副本二级存储,放在2U4节点服务器上跑,使用万兆交换机相连,写的速度能达到300M/s,但是读的速度只能达到30~40MB/s.分析,读速度之所以这么慢.主要是因为:为了实现重删,我们采用了数据变长分块,生成hash,最后利用全局hash库过滤重复数据,最后数据保存到当前正在使用的map文件.当多个文件同时写入的时候这个过程,把连续的数据变得离散. 使得读取数据的时候,硬盘每一次都是随机读.读性能相当差.为了提高读性能,我们对数据模型做了修改,对入口做了分组,把分组连续的数据做成定长1M块存储. 重构后,读性能确实上升了一倍,但是程序的稳定性不行.连续写入数据几个小时后,程序性能就开始慢慢往下降,最后直接内存溢出. 直接内存 使用htop看程序内存占用,发现占用的内存确实比实际配置的高很多.造成这种原因,因为我们使用了java nio 提供的直接内存接口,这部分内存都不是从堆中分配的: 显式分配 ByteBuffer.allocateDirect(int size) 程序里一些循环里面的临时ByteBuffer是使用直接内存生成的.这一部分,都改过来: ByteBuffer.allocate 使用了nio内存映射: FileChannel.map(MapMode mode,long position, long size) 我们的hash索引是保存在文件里,当布隆过滤器没有命中,使用内存映射来真实读取.因为设计上的原因,基本上不会释放. jvm参数配置有问题 -XX:+DisableExplicitGC 我们使用了DisableExplicitGC,因为大量Direct ByteBuffer 所以最后导致OOM.看了很多文章都建议不要开启. DirectMemory 默认的大小是等同于JVM最大堆.所以最终看起来程序内存比我们配置的-Xmx 高很多. 堆内内存 开启** G1 gc log**后,查看日志发现有大量的mix gc,感觉这部分影响了系统性能. -XX:+UseG1GC -XX:+PrintGCDetails-verbose:gc -Xloggc:gc.log 使用jmx内存监控 jstatd -J-Djava.security.policy=jstatd.all.policy 监测程序内存情况,发现写入数据的时候old eden会不断往上涨,然后引发mix gc,不断重复这个过程.而Survivor eden不怎么变.就觉得非常奇怪.为什么直接就在old eden分配呢? 对比老版本,看看有没有相同的情况,老版本在相同的jvm 参数下,跑的时候内存比较稳定.都是在servivor eden 上分配的.这下更苦逼,基本可以说明是:我们改出来的. 使用jmap 把整个程序的堆内存dump下来,看了看占了堆内存90%的是long[]和byte[]再仔细细分,前者主要是用在了布隆过滤器上,后者也多是数据传递时候的一些数组.看不出什么问题. 偶然,把老版本的堆内存参数-Xmx配置低一些,发现老版本也出现相识的问题.这下好了,原来问题一直有,只是我们现在分配的数据多了,大了,更容易暴露出来. 重新观察新程序gc,发现刚开始的时候,其实新版本也是在servivor… Continue reading 项目的jvm内存分析
Linux文件系统基础
前面 本文在摘录了一些基本概念 文件描述符 文件描述符是一些小值整数,用于文件系统在处理文件的时候,标识被处理文件. 因此文件描述符的总数也就是系统可以打开的文件的最大数量 当Linux系统开始运行的时候,有三个文件描述符已经被使用: 标准输入:0 标准输出:1 标准错误:2 其他文件的文件描述符,在调用open函数时返回.文件描述符有操作系统分配,每次分配最小的. 库函数 系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思。面向的是硬件。而库函数调用则面向的是应用开发的,相当于应用程序的api,采用这样的方式有很多种原因: 双缓冲技术的实现。 可移植性。(系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。) 底层调用本身的一些性能方面的缺陷。 让api也可以有了级别和专门的工作面向。 函数库调用 系统调用 在所有的ANSI C编译器版本中,C库函数是相同的 各个操作系统的系统调用是不同的 它调用函数库中的一段程序(或函数) 它调用系统内核的服务 与用户程序相联系 是操作系统的一个入口点 在用户地址空间执行 在内核地址空间执行 它的运行时间属于“用户时间” 它的运行时间属于“系统”时间 属于过程调用,调用开销较小 需要在用户空间和内核上下文环境间切换,开销较大 在C函数库libc中有大约300个函数 在UNIX中大约有90个系统调用 典型的C函数库调用:system fprintf malloc 典型的系统调用:chdir fork write brk; /proc文件系统 Linux将一切看做文件,硬件设备在文件系统中也有相应的文件 /proc文件系统,可以看做是一个特殊的文件系统,每一个独立的硬件在这个系统中,都对应着一个文件,用户可以通过proc文件系统像访问文件一样来访问硬件设备。 也可以通过ps -ef |grep xxx获取程序pid,然后在/proc/pid/文件夹下查看该程序的运行情况. 参考 linux文件写过程 Linux 文件操作总结