作为使用第三方(阿里云)的我司来说,我个人觉得很多钱是浪费了。在知乎上有人讨论自建和上云哪个省钱,其实还是要看在公有云上怎么用,公有云很多资源具有召之即来挥之即去的特性,实际上是可以最大限度的去压榨的。做容量规划的目的,很简单,向规划要资源利用率、投入产出比,算的是笔经济账。对个人而言,替公司节约几十甚至上百万的费用,这种贡献自然会得到丰厚的回报。对企业而言,节约了费用和开支,资源可以使用到其他地方,继而可以提高竞争力。所以,容量规划是必须而且重要的。
我个人构思的步骤有如下,虽不成熟,但是独立思考所得。容量规划有个前置条件,即系统的性能瓶颈已经或者大部分都被识别,在做规划的时候尽量保守一些。大致步骤和关键点:
采集线上流量特征,建立流量模型、生成压测模型;
笔者是电商行业,所以对于高频的营销工具也需要单独压测,比如拼团购、限时折扣、拉人应用等。这些工具都是高并发、突发性流量的主要来源。
理论上,在系统不崩溃、响应正常的前提下,资源利用率的平均值在80-90%,是最优的利用率,它最大限度的压榨了机器的价值。但是很明显,人工构建的系统,想要达到这种级别的利用率而系统一切ok的话,可能要投入更多的研发资源来优化,对于中小企业来说,可能就有点缘木求鱼了,毕竟业务才是王道。退而求其次的话,资源利用率降低一个档次,在60-80%,就是一个比较合理的利用率(压榨)了。
| 利用率% | 级别 | 措施 |
|---|---|---|
| [0,30] | 闲置 | 缩容减支 |
| [30,50] | 适当 | 观察 |
| [50,70] | 合理 | 观察 |
| [70,90] | 充分 | 警觉和扩容 |
| [90,100] | 过量 | 必须扩容 |
监控指标的确定:
最近,在构思一套内部环境服务的监控系统,起码的功能是能识别到业务进程异常(进程级别的),退出后自动拉起。
找到了supervisor,了解基本功能后,觉得它在分布式方面还存在不足之处,所有配置分散在单机上。鉴于它的技术符合目前需要练习python技术栈。所以,准备对其源代码进行解构、分析和学习。
源码研究和学习,起码要对该工具如何使用有个基本的掌握。
Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。
它依赖第三方的medusa来处理网络请求。medusa的源码也值得学习和研究。
类似于docker所在服务器运行的守护进程,负责响应客户端的命令行、受监控进程的监控、重启、受控子进程的标准输入输出的日志、生成和处理与子流程生命周期中相对应的“事件”。配置文件一般为/etc/supervisord.conf。
控制台,和supervisord交互。通过控制台,用户可以连接到不同的supervisord进程( 通过UNIX domain socket or an internet (TCP) socket),查看supervisord的控制进程的状态。读取/etc/supervisord.conf下的[supervisorctl]内容作为配置。
supervisord的浏览器控制台。仅支持单机模式,就是说,N台服务器安装了supervisor的话,就有N个webServer,它们彼此之间并没有关联,所以也没有一个集中化的界面统一管理。
有个php的解决方案:https://blog.csdn.net/geerniya/article/details/80107761
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 | pstree |
在Linux中,用户程序装入系统形成一个进程的实质是操作系统为用户程序提供一个完整的运行环境。进程的运行环境是由它的程序代码和程序运行所需要的数据结构以及硬件环境组成的。进程的运行环境主要包括:
1.进程空间(内存)中的代码和数据、各种数据结构、进程堆栈和共享内存区等。
2.环境变量:提供进程运行所需的环境信息。
3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。
4.进程访问设备或者文件时的权限。
5.各种硬件寄存器。
6.地址转换信息。
一个进程在操作系统中执行,有两种状态:内核态和用户态。如果当前运行的是用户程序(用户代码),那么对应进程就处于用户),如果出现系统调用或者发生中断,那么对应进程就处于内核模式(核心态)。
为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块 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包含以下内容:
表示进程的状态, 在进程执行的时候,它会有一个状态,这个状态对于进程来说是很重要的一个属性。包括:可运行、可中断的等待状态、不可中断的等待状态、将死、暂停、换入/换出。
最近在看一本讲数据库架构的英文书,书中很多次提及到一个叫缓存的词语,在我们商城的业务系统中也经常听到缓存这个词语。于是百度找到这篇文章。内心觉得总结很到位。转自:缓存技术原理
一、前言
应用中使用缓存技术,往往可以大大减少计算量,有效提升响应速度,让有限的资源服务更多的用户。但是,似乎还没有一种缓存方案可以满足所有的业务场景,我们需要根据自身的特殊场景和背景,选择最适合的缓存方案,尽量以最小的成本最快的效率达到最优的目的。本文将从多个方面对缓存进行分析,以便作为选择缓存方案的考量。
二、文章要点
三、缓存的理解 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 分布式缓存特性
问题描述:
我们的tomcat启动了apr启动https端口,我设置了systemd的tomcat.service的文件,使用systemctl start tomcat,始终无法识别apr的环境变量。研究了一会后解决。
先贴tomcat.service最终设置,只需加一行配置即可。
1 | [Unit] |
关键点:
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
阿里云上的安全监测提示:
近日,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 | <dependency> |
2、编译。
1 | cd "代码路径" |
编译过程如果不顺利,或下载不下来文件,自己百度处理。
当然,也可以参考jenkins源码编译和打包(20180408更新) 中的部分步骤,像nodeys的没有就不操作。自己搭建私有库,我是现成的。不自己搭建的话,估计问题也不会太大。
3、踩过的坑。版本问题,编译的版本一定要和当前的版本保持一致,至少不能跳大版本,否则启动不起来,甚至会有各种意想不到的问题。版本一致就顺风顺水。