🌓

中小型网站的容量规划纲要

目的

作为使用第三方(阿里云)的我司来说,我个人觉得很多钱是浪费了。在知乎上有人讨论自建和上云哪个省钱,其实还是要看在公有云上怎么用,公有云很多资源具有召之即来挥之即去的特性,实际上是可以最大限度的去压榨的。做容量规划的目的,很简单,向规划要资源利用率、投入产出比,算的是笔经济账。对个人而言,替公司节约几十甚至上百万的费用,这种贡献自然会得到丰厚的回报。对企业而言,节约了费用和开支,资源可以使用到其他地方,继而可以提高竞争力。所以,容量规划是必须而且重要的。

容量规划步骤

我个人构思的步骤有如下,虽不成熟,但是独立思考所得。容量规划有个前置条件,即系统的性能瓶颈已经或者大部分都被识别,在做规划的时候尽量保守一些。大致步骤和关键点:

  • 确定系统资源消耗类型(计算密集耗cpu、数据密集吃内存、网络或读写密集吃io),掌握系统在某资源配置情况下,能够支持的并发数。建立各系统的并发模型。
  • 掌握系统当前线上环境日常流量特征,并基于该特征制定一个流量模型。
  • 基于流量模型定制一个资源的基准水位,以达到支持日常访问较合理的资源利用率。
  • 核心服务的流量监控报警方案及自动扩容、缩容方案。

系统并发压测方案

采集线上流量特征,建立流量模型、生成压测模型;

笔者是电商行业,所以对于高频的营销工具也需要单独压测,比如拼团购、限时折扣、拉人应用等。这些工具都是高并发、突发性流量的主要来源。

资源利用率的判定

理论上,在系统不崩溃、响应正常的前提下,资源利用率的平均值在80-90%,是最优的利用率,它最大限度的压榨了机器的价值。但是很明显,人工构建的系统,想要达到这种级别的利用率而系统一切ok的话,可能要投入更多的研发资源来优化,对于中小企业来说,可能就有点缘木求鱼了,毕竟业务才是王道。退而求其次的话,资源利用率降低一个档次,在60-80%,就是一个比较合理的利用率(压榨)了。

利用率% 级别 措施
[0,30] 闲置 缩容减支
[30,50] 适当 观察
[50,70] 合理 观察
[70,90] 充分 警觉和扩容
[90,100] 过量 必须扩容

监控方案

监控指标的确定:

  • TCP连接指标
  • 内存使用率指标
  • cpu使用率指标
  • 磁盘IO指标
  • db的监控指标系列

阅读全文

Supervisor源码研究和学习

出发点

最近,在构思一套内部环境服务的监控系统,起码的功能是能识别到业务进程异常(进程级别的),退出后自动拉起。
找到了supervisor,了解基本功能后,觉得它在分布式方面还存在不足之处,所有配置分散在单机上。鉴于它的技术符合目前需要练习python技术栈。所以,准备对其源代码进行解构、分析和学习。

概览

源码研究和学习,起码要对该工具如何使用有个基本的掌握。

Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。

medusa

它依赖第三方的medusa来处理网络请求。medusa的源码也值得学习和研究。

supervisord

类似于docker所在服务器运行的守护进程,负责响应客户端的命令行、受监控进程的监控、重启、受控子进程的标准输入输出的日志、生成和处理与子流程生命周期中相对应的“事件”。配置文件一般为/etc/supervisord.conf。

supervisorctl

控制台,和supervisord交互。通过控制台,用户可以连接到不同的supervisord进程( 通过UNIX domain socket or an internet (TCP) socket),查看supervisord的控制进程的状态。读取/etc/supervisord.conf下的[supervisorctl]内容作为配置。

Web Server

supervisord的浏览器控制台。仅支持单机模式,就是说,N台服务器安装了supervisor的话,就有N个webServer,它们彼此之间并没有关联,所以也没有一个集中化的界面统一管理。

有个php的解决方案:https://blog.csdn.net/geerniya/article/details/80107761

XML-RPC Interface

The same HTTP server which serves the web UI serves up an XML-RPC interface that can be used to interrogate and control supervisor and the programs it runs.

不足

优点:
- 可以将非后台运行程序后台运行
- 自动监控,重启进程

缺点:
- 不能管理后台运行程序
- 对多进程服务,不能使用kill关闭

源码分析

源码分析步骤:

1、clone代码到本地;

2、本地做supervisord的配置

3、参考别写的源码文章,找到程序入口,阅读代码

4、debug若干次,追中代码运行逻辑

阅读全文

操作系统进程原理

这篇文章是研习supervisor源代码的副产品,主要理解supervisor的驱动原理和操作系统对进程管理的一些基本知识。

理解什么是进程

百度百科定义如下:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

进程是操作系统对资源的一个抽象。
操作系统是计算机的管家,掌控着计算机内部的一切资源的分配、调度、回收。
而进程可以理解为计算机资源调度的一个基本单元。用播放电影来举个形象的例子,进程就是电影一针一针的画面,而程序就是播放这部电影的一个统称,电影没开始播放前,得准备放映机(cpu),电影胶片(内存)。放音机齿轮转动就好比cpu的时钟脉冲,每秒扫过N个胶片(进程被调度),图像被光打到幕布上(计算机的输出设备)。

换一个角度看操作系统的进程,linux系统开机启动到系统启动完毕,从进程的角度看就是一生二、二生三、三生万物的感觉。我们面对的就是进程的一课大树,它的源头就是进程号为1(名叫systemd)的进程,systemd是Linux下的一种负责init的进程,那字母d就是daemon的标记,又比如apache的http服务,它的进程也有个字母d,httpd。可以运行pstree命令来体验一下这种子子孙孙无穷匮也。ps和systemctl命令也有类似效果。

1
2
3
pstree
ps axjf
systemctl status

进程运行环境

在Linux中,用户程序装入系统形成一个进程的实质是操作系统为用户程序提供一个完整的运行环境。进程的运行环境是由它的程序代码和程序运行所需要的数据结构以及硬件环境组成的。进程的运行环境主要包括:

  • 1.进程空间(内存)中的代码和数据、各种数据结构、进程堆栈和共享内存区等。

  • 2.环境变量:提供进程运行所需的环境信息。

  • 3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。

  • 4.进程访问设备或者文件时的权限。

  • 5.各种硬件寄存器。

  • 6.地址转换信息。

Linux下的进程模型

从PCB中了解进程模型

一个进程在操作系统中执行,有两种状态:内核态和用户态。如果当前运行的是用户程序(用户代码),那么对应进程就处于用户),如果出现系统调用或者发生中断,那么对应进程就处于内核模式(核心态)。

为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块 PCB(Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构,每一个进程均有一个 PCB,在创建进程时,建立 PCB,伴随进程运行的全过程,直到进程撤消而撤消。PCB 记录了操作系统所需的,用于描述进程的当前情况以及控制进程运行的全部信息(如打开的文件、挂起的信号、进程状态、地址空间等等)。在linux中这个PCB是一个叫做task_struct的结构体。

task_struct 在linux中,每一个进程都有一个进程描述符,这个”进程描述符”是一个结构体名字叫做task_struct,在task_struct里面保存了许多关于进程控制的信息。

task_struct是Linux内核的一种数据结构,它会被装载到RAM里并包含进程的信息。

每个进程都把它的信息放在task_struct这个数据结构里面,而task_struct包含以下内容:

进程状态(State)

表示进程的状态, 在进程执行的时候,它会有一个状态,这个状态对于进程来说是很重要的一个属性。包括:可运行、可中断的等待状态、不可中断的等待状态、将死、暂停、换入/换出。

阅读全文

将有序数组转换为二叉搜索树

最近在刷leetcode算法的入门题,刷到二叉树,一开始浑浑噩噩,后来掌握了套路,自己搞定一个,而且很优雅,比留言中的大部分都优雅,嗯,写个日志自嗨一把。所有刷题都提交到我的github上了,具体位置:windanchaos的github 1234567891011121314151617181920题目要求:将一个按照升序排列的有序数组,转换为一棵高度平衡...

阅读全文

缓存技术原理

最近在看一本讲数据库架构的英文书,书中很多次提及到一个叫缓存的词语,在我们商城的业务系统中也经常听到缓存这个词语。于是百度找到这篇文章。内心觉得总结很到位。转自:缓存技术原理

一、前言

应用中使用缓存技术,往往可以大大减少计算量,有效提升响应速度,让有限的资源服务更多的用户。但是,似乎还没有一种缓存方案可以满足所有的业务场景,我们需要根据自身的特殊场景和背景,选择最适合的缓存方案,尽量以最小的成本最快的效率达到最优的目的。本文将从多个方面对缓存进行分析,以便作为选择缓存方案的考量。
二、文章要点

三、缓存的理解 3.1 狭义的理解

缓存指的是 CPU 缓存,当 CPU 要读取一个数据时,首先从 CPU 缓存中查找,找到就立即读取并送给 CPU 处理;没有找到,就从速率相对较慢的内存中读取并送给 CPU 处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存。

3.2 广义的理解

凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为缓存。

3.3 缓存的优点

如下,一个 Web 应用架构一般有如下几层:

在此架构的不同层级之间,都可以存在缓存。比如:

总结来说,缓存在如下三个方面做了提升:

四、CPU 缓存简介

CPU 缓存(Cache Memory)是位于 CPU与 内存之间的临时存储器,它的容量比内存小的多,但是交换速率却比内存要快得多。缓存的出现主要是为了解决 CPU 运算速率与内存读写速率不匹配的矛盾,因为 CPU 运算速率要比内存读写速率快很多,这样会使 CPU 花费很长时间等待数据到来或把数据写入内存。在缓存中的数据是内存中的一小部分,但这一小部分是短时间内 CPU 即将访问的,当 CPU 调用大量数据时,就可避开内存直接从缓存中调用,从而加快读取速率。由此可见,在 CPU 中加入缓存是一种高效的解决方案,这样整个内存储器(缓存+内存)就变成了既有缓存的高速率,又有内存的大容量的存储系统了。 缓存基本上都是采用 SRAM 存储器,存储器在计算机内部的组织方式如下图所示:

越往上,存储器的容量越小、成本越高、速度越快。由于 CPU 和主存之间巨大的速度差异,系统设计者被迫在 CPU 寄存器和主存之间插入了一个小的 SRAM 高速缓存存储器称为 L1 缓存,大约可以在 2-4 个时钟周期(计算机中最小的时间单位)内访问。再后来发现 L1 高速缓存和主存之间还是有较大差距,又在 L1 高速缓存和主存之间插入了 L2 缓存,大约可以在 10 个时钟周期内访问。后面还新增了 L3 等,于是,在这样的模式下,在不断的演变中形成了现在的存储体系。
五、分布式缓存原理 5.1 本地缓存

本地缓存可能是大家用的最多的一种缓存方式了,如 Ehcache、Guava Cache 等,它是在应用中的缓存组件,其最大的优点是应用和 cache 是在同一个进程内部,请求缓存非常快速,没有过多的网络开销等,在单应用不需要集群支持或者集群情况下各节点无需互相通知的场景下使用本地缓存较合适; 同时,它的缺点也是因为缓存跟应用程序耦合,多个应用程序无法直接的共享缓存,各应用或集群的各节点都需要维护自己的单独缓存,对内存是一种浪费。

5.2 分布式缓存特性

阅读全文

Systemd 添加tomcat服务,开机启动,支持apr

问题描述:
我们的tomcat启动了apr启动https端口,我设置了systemd的tomcat.service的文件,使用systemctl start tomcat,始终无法识别apr的环境变量。研究了一会后解决。
先贴tomcat.service最终设置,只需加一行配置即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=java tomcat project
After=syslog.target network.target

[Service]
Type=forking
User=user
Group=user
EnvironmentFile=/opt/apache-tomcat/bin/config
ExecStart=/opt/apache-tomcat/bin/startup.sh
ExecReload=
ExecStop=/arthas/servers/apache-tomcat-8.5.4-80/bin/shutdown.sh
PrivateTmp=true

[Install]
WantedBy=multi-user.target

关键点:

EnvironmentFile=/opt/apache-tomcat/bin/config 的设置。
文件内容如下,是启动tomcat的环境变量:

1
LD_LIBRARY_PATH=/usr/local/apr/lib:$LD_LIBRARY_PATH

原理:
1、/etc/profile或者/etc/security/limit.d这些文件中配置的环境变量仅对通过pam登录的用户生效,而systemd是不读这些配置的,所以这就造成登录到终端时查看环境变量和手动启动应用都一切正常,但是systemd无法正常启动应用。
2、EnvironmentFile:该字段指定软件自己的环境参数。

参考:
https://blog.csdn.net/lizao2/article/details/81030380
https://www.cnblogs.com/jhxxb/p/10654554.html

阅读全文

git换行符冲突CRLF、LF的解决方案

git在维护版本库的时候统一使用的是LF,这样就可以保证文件跨平台的时候保持一致。在Linux下默认的换行符也是LF,那也就不存在什么问题。在Windows下默认的换行符是CRLF,那么我们需要保证在文件提交到版本库的时候文件的换行符是LF,通常来说有两种方法: 123456# 在工作区使用CRLF,使用git commit提交的时候git帮你把所有的CRL...

阅读全文

编程求:∑1+∑2+……+∑100

最近在践行代码,先把尚学堂的习题做完,遇到有点代表的就发个日志。以下算法时间复杂度为N,还可以。这个好像是用了某种算法,具体叫动态规划法。 12345678910111213141516/* 103. 【上机】编程求:∑1+∑2+……+∑100 这里输入最大数100作为参数 */ public void sigma(int num)...

阅读全文

jenkins修复最新Apache Struts远程代码执行漏洞(CVE-2016-1000031)

修复问题描述

阿里云上的安全监测提示:
近日,Apache软件基金会(ASF)向Apache Struts项目管理员发布了关于CVE-2016-1000031漏洞的安全公告,其中披露一个Commons FileUpload库的历史高危漏洞CVE-2016-1000031,而2.3.x系列版本的Apache Struts2仍在使用低版本的Commons FileUpload库,该库作为Struts2的一部分,被用作文件上传的默认机制,远程攻击者利用该漏洞可直接获得服务器权限。2.5.12以上版本的Struts2暂不受影响。
注意:java类web应用的修复一般都需要重启应用
方案一:
升级至2.5.18及以上版本的Struts2,官方下载链接:https://struts.apache.org/download.cgi
方案二:
升级Struts2依赖的Commons FileUpload库版本至最新1.3.3,官方下载地址:https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi

我这里是思路就是采用方案二。

怎么修复

整体思路很简单,下载源代码,修改需要升级的引用包版本,重新编译构建发布。
1、clone jenkins的源代码到本地,修改引用包的版本。这里直接用我的结果即可,文件为jenkins/core/pom.xml

1
2
3
4
5
6
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
<!--<version>1.3.3-jenkins-2</version> -->
</dependency>

2、编译。

1
2
cd "代码路径"
mvn clean package -pl war -am -DskipTests -Dfindbugs.skip -X

编译过程如果不顺利,或下载不下来文件,自己百度处理。
当然,也可以参考jenkins源码编译和打包(20180408更新) 中的部分步骤,像nodeys的没有就不操作。自己搭建私有库,我是现成的。不自己搭建的话,估计问题也不会太大。

3、踩过的坑。版本问题,编译的版本一定要和当前的版本保持一致,至少不能跳大版本,否则启动不起来,甚至会有各种意想不到的问题。版本一致就顺风顺水。

阅读全文

【计算机理论基础】计算机是如何做运算的

由低向上的学习计算机是一条比较漫长的道路。但是,得来的知识却是体系化的。而且越到上边,学习的理解的效率是越高的(暂且自我欺骗,毕竟还没达到那高度)
下面就最近研究和学习做一个复盘。以问题出发为脉络。
1、计算机是怎么做运算的?
关键字:二进制、逻辑门
2、在问题1的基础上又问:为什么是二进制?
3、CPU是如何工作?

1、计算机是怎么做运算的?

回答这个问题,要先弄懂人类在使用10进制做计算时的方法,不赘述。
10进制方法迁移到二进制。基本的加法、乘法(可转成进位的加法),减法转成加法实现,除法转成乘法实现(这个我还没深究)。
进制之间可以平滑的换算。

数和进制的抽象

(这是我独立思考得出的,未见有人说过,或者有但我不了解)。
位和进制大小、进位。是三个基本元素。
位是进位中的位,是进制数的承载单元。位只能承载(0到进制-1)的数。比如:10进制中,一个位可以放0-9的数字,到10的时候就需要进位。二进制,最大放1,到2就要进位。
进制大小:就是所谓的2、10、16。
进位:位中承载的数等于进制大小时,发生的高位+1行为。

所以,可以有5进制。甚至可以有100进制,当然如果能够找到这么多数字的象征,恐怕人类的大脑处理起来也是费尽的。
问题又来了,为什么人类有进制这种抽象,我觉得主要还是来源于认知的范围是有限的,而认知的对象是无限的。之所以说认知范围是有限的,主要是人的身体机能决定的,不能同时(并行)思考和处理多个问题。以有限的认知认识无限,只能将无限的进行分而治之。数字是对现实世界和数量有关的一种抽象。位,就是数字抽象的基本单元。对于人类来说,现实世界的物质是无限的,小到分子原子、大到宇宙万物。所以用进制数可以表示一个特定的数量的概念。

如果存在一个主体(比如上帝),ta使用的是无限进制,宇宙万物都囊括在其中,它不用进位。每个事物都有是唯一的,那么人类的进制就已经没有了意义,ta能使用无限进制的前提是掌握了无限事物的信息,超人类思维的存在。这就是无限这个抽象的力量。

什么是运算

传送门
人类为什么要做运算呢?因为人类的认知是有限的啊,为了得到暂时无法获得的信息,基于已有的信息进行信息的变化和组合,就生成了运算。所以,如果人类可以直接获得任何信息,比如看到一个平面物体,便知道它的面积和体积,那基于几何学的长宽高、积分之类的运算就不再具有它的价值,但这目前还只是一种思维游戏,人类还是渺小的。
这里举个例子:
国王统治了100个小城邦,他欲了解各城邦的粮食产量这个信息,以备决策。最简单的方式就是,统计各城邦的产量,然后全部相加。
如果没有数字和运算,他要得到信息,需要把100个城邦的粮食搬到一起,进行称重了。
插个题外话,统计出来的数字只是一种近似值,为什么呢?因为在实操的过程中,城邦是可以谎报数量的,可以报大或报小,加起来的数已经不是国王心中想要的那个数了,但是这也没有办法,先解决有和无的问题,只要偏差不大的离谱,是可以容忍和妥协的。妥协这词在计算机的实现中也是常见的。
物理学中的很多问题都是靠运算得出的,比如光速是怎么得来的(人类一开始测量得到的光速也只是近似值)?天体物理学又靠什么说宇宙在膨胀?
所以,再不要把运算限定在10进制了,它只是众多进制中人类习以为常的一种而已。
结合进制和运算:

阅读全文