Rootop 服务器运维与web架构

2018-11-26
发表者 Venus
nethogs查看进程网络流量统计已关闭评论

nethogs查看进程网络流量统计

centos安装:
1、安装epel源
2、yum install nethogs

ubuntu安装:
apt install nethogs

root@venus:~# nethogs -h
usage: nethogs [-V] [-h] [-b] [-d seconds] [-v mode] [-c count] [-t] [-p] [-s] [device [device [device …]]]
-V : prints version.
-h : prints this help.
-b : bughunt mode – implies tracemode.
-d : # 动态刷新时间间隔,默认1秒
-v : view mode (0 = KB/s, 1 = total KB, 2 = total B, 3 = total MB). default is 0.
-c : number of updates. default is 0 (unlimited).
-t : tracemode.
-p : sniff in promiscious mode (not recommended).
-s : sort output by sent column.
-a : monitor all devices, even loopback/stopped ones.
device : device(s) to monitor. default is all interfaces up and running excluding loopback

When nethogs is running, press:
q: quit # 退出
s: sort by SENT traffic # 按照发送流量排序
r: sort by RECEIVE traffic # 按照接受流量排序
m: switch between total (KB, B, MB) and KB/s mode # 切换总量(KB,B,MB) / 每秒KB速率

2018-11-21
发表者 Venus
linux下打包vue项目已关闭评论

linux下打包vue项目

nodejs下载地址:https://nodejs.org/en/download/
下载二进制版本解压并移动改名为 /usr/local/node

创建node、npm命令软链接,方便调用:

[root@jenkins ~]# ln -s /usr/local/node/bin/node /usr/local/bin/node 
[root@jenkins ~]# ln -s /usr/local/node/bin/npm /usr/local/bin/npm 

# 安装cnpm,国外源下载速度太慢,安装国内淘宝源

[root@jenkins ~]# npm install -g cnpm --registry=https://registry.npm.taobao.org

# cnpm创建软连接

[root@jenkins ~]# ln -s /usr/local/node/bin/cnpm /usr/local/bin/cnpm 

对当前nodejs项目打包
1、根据依赖安装插件

[root@jenkins workspace]# cnpm install # 会自动根据 package.json 中定义的参数自动下载依赖

2、打包

[root@jenkins workspace]# cnpm run build

打出来的包在dist目录下。

注意:
npm run xxx
xxx参数取决于项目根目录下 package.json 中的scripts键中的子key

"scripts": {
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build --mode development",
"public": "vue-cli-service build --mode production",
"public-test": "vue-cli-service serve --mode production",
"lint": "vue-cli-service lint"
}

pm2 start xxx.js xxx.js是入口文件,不一定是js文件,也可能是一个可执行文件

依赖的包也在package.json中定义。
比如在 package.json 中会有 dependencies 关键词部分的配置,比如

"dependencies": {
"core-js": "^3.6.4",
"vue": "^2.6.12"
},
"devDependencies": {
"@vue/component-compiler-utils": "^1.3.1",
"@vue/cli-plugin-babel": "~4.3.0",
"@vue/cli-plugin-eslint": "~4.3.0",
"@vue/cli-plugin-router": "~4.3.0",
"@vue/cli-plugin-vuex": "~4.3.0",
"@vue/cli-service": "~4.3.0",
"babel-eslint": "^10.1.0",
"compression-webpack-plugin": "^3.0.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"vue": "^2.6.12",
"vue-template-compiler": "^2.6.12"
}

在执行 npm install 的时候会自动安装上面所有的依赖。依赖会下载到当前目录的 node_modules 文件夹中。

安装插件命令 cnpm install xxx –save 会自动保存到 package.json
注意引入的资源大小写,在windows下打包正常,在linux下打包报错,发现是引入的一个字体文件后缀大小写问题。

2018-11-13
发表者 Venus
redis实现分布式锁已关闭评论

redis实现分布式锁

以下为测试分布式锁的实现方法。

场景:
比如50个人向B转账,B的余额当前为0,转50次,每次1元,理论来说B的余额应该为50元。
当在高并发的情况下,那么最终结果就不一定是50了。

现在有张表名为balance,3个字段id(自增),name(姓名),balance(余额)

现在用php模拟一下简单的转账操作。

<?php header("Content-type =>  text/html; charset=utf-8");
// session start
define("SESSION_ON", true);

// define project's config
define("CONFIG", '/conf/web.php');

// debug switch
define("DEBUG", true);

// include framework entrance file
include('../common.php');

use pt\framework\debug\console as debug;
use pt\framework\template as template;
use pt\tool\page as page;
use pt\framework\db as db;

include(COMMON_PATH.'web_func.php');

$db = db::init();

// 查询B用户余额
$balance = "select balance from balance where id = 1;";
$balance = $db -> prepare($balance) -> execute();
$balance = $balance[0]['balance'];

// B余额加1
$sql = "update balance set balance = :balance + 1 where id = 1;";
$rs = $db -> prepare($sql) -> execute(array(':balance' => $balance));

使用jmeter并发50测试且50个请求全部成功。去查看数据库。

可以看到数据库中balance字段值为44,不是理论的50元。
原因就是在高并发情况下出现了问题。
比如有2个请求同时从数据库中获得了一样的余额,比如1,第一个请求先进行了update操作但是还没结束,
第二个请求发现第一个请求正在更新数据库,第一个修改请求会将balance表的id=1这条数据处于行锁状态(innodb引擎+索引才能实现行锁)。
这样第二个请求就处于等待状态,等待第一个请求update完成并释放行锁后,再更新id=1的数据,问题来了。
第一个请求已经将余额修改为2,第二个请求也把余额改为2了。(其实并没有真正更新,发现一样就不改了,在sqlyog中会提示(0 row(s) affected),影响了0行)
(完整的转账应该至少3条记录要通过事务更新,from减,to加,插入资金流水表)

现在为了解决这个问题,引入redis,通过setnx这个方法实现,具体解释请百度。
当redis中存在to(我这里把to的用户id做为key)这个key时,则停止转账。

<?php header("Content-type =>  text/html; charset=utf-8");
// session start
define("SESSION_ON", true);

// define project's config
define("CONFIG", '/conf/web.php');

// debug switch
define("DEBUG", true);

// include framework entrance file
include('../common.php');

use pt\framework\debug\console as debug;
use pt\framework\template as template;
use pt\tool\page as page;
use pt\framework\db as db;

include(COMMON_PATH.'web_func.php');

$db = db::init();

$to = 1;  // 用户id做为key

try
{
    $redis = new Redis();
    $redis -> connect('127.0.0.1', 6379);
    $redis -> auth('111111');
    $connected = $redis -> ping();
}
catch(Exception $e)
{
    echo '连接失败:' . $e -> getMessage();
    exit;
}

// 获取用户余额
$balance = "select balance from balance where id = 1;";
$balance = $db -> prepare($balance) -> execute();
$balance = $balance[0]['balance'];

$expire = 60;  // key超时时间
$key = $to;
$content = 'running';
$rs = $redis -> setnx($key, $content);

if ($rs === true) // 加锁
{
    $redis -> expire($key, $expire);  // 设置key超时时间,防止某个机器加锁以后挂掉造成key死锁(一直存在)。
    $sql = "update balance set balance = :balance + 1 where id = 1;";
    $rs = $db -> prepare($sql) -> execute(array(':balance' => $balance));

    if ($rs === false)
    {
        echo 'add balance failed';
    }
    else
    {
        echo 'add balance success';
    }

    $redis -> delete($to); // 删除锁
}
else
{
    //echo 'lock false , lock by others' . PHP_EOL;
    //echo 'after ' . $redis -> ttl($key) . 's release';
    header('HTTP/1.1 403 Forbidden');  // 这里输出403错误方便jmeter中查看。实际中可能返回个友好的错误提示,比如请重试。
}

再用jmeter并发50测试。

发现有34个请求成功,16个失败,总共50个请求。
再去看数据库中balance字段。余额为34。


这样就通过redis实现了分布式锁,当有多个服务器做负载均衡时,每次转账都会先请求redis,查这个用户是否存在key,防止出现同一时间转账导致结果错误。
如有错误,请指正。

PS:
另外我觉得也可以通过消息队列实现,排队转账。

2018-11-07
发表者 Venus
Gitlab+jenkins自动构建指定分支已关闭评论

Gitlab+jenkins自动构建指定分支

注意点1:
在jenkins中,源码管理 Git Branches to build 中指定的分支名(比如一个分支名叫simon),在jenkins中手动点击构建时,jenkins拉取的分支为simon。

注意点2:
当在gitlab中配置了web钩子当触发推送事件到jenkins中时,jenkins拉取的分支为git push推送时所在的分支。
比如当前代码在master分支,git push时触发推送事件,jenkins会拉取master分支。
如果当前代码在test分支,git push时触发推送事件,jenkins会拉取test分支。
(通过钩子触发的构建,在 源码管理 – Git – Branches to build 中配置的分支名并不会被jenkins拉取构建)

这样就失去了我的本意(拉取固定分支)。

实现指定分支构建方法:
1、
在jenkins中有个插件名叫 Git Parameter ,安装以后在 参数化构建过程 中会多出一个参数也叫Git Parameter。(具体配置百度搜索即可)
这个可以实现多分支构建,在构建时,并不会立即构建,他会先拉取代码,然后分析有多少分支,并列出来让你手动去选择分支,再去构建。
但是这样就无法实现自动化构建了(必须人工选择)。

2、
我所使用的方法:
构建触发器Build when a change is pushed to GitLab. GitLab webhook URL: http://xxxxxx 这里有个 高级 选项。
选择 Filter branches by name ,然后 Include 里写要构建的分支,比如simon。

PS:
印象里这个webhook地址是需要安装 GitLab Plugin 这个插件才会出现url地址。

这样配置以后当代码推送时,如果推送的分支是simon分支,则会开始自动构建,其它分支推送时则不会触发自动构建。
(当一个分支名为simon2时,也不会构建)

这样就实现指定分支推送自动构建了。

2018-10-19
发表者 Venus
关于mysql视图运维过程中的注意事项已关闭评论

关于mysql视图运维过程中的注意事项

# 今天遇到的问题
mysql备份脚本无法备份,提示错误不能锁表:

mysqldump: Got error: 1045: Access denied for user 'xxx'@'%' (using password: YES) when using LOCK TABLES

在发现问题的前一天删过一个历史遗留账号(备份脚本之前一直是运行正常的)。

在备份脚本加入 --skip-lock-tables 参数不锁表备份,提示错误:
mysqldump: Couldn't execute 'SHOW FIELDS FROM `vm_dataforradarshow`': SELECT command denied to user ''@'%' for column 'prodId' in table '表名已删除' (1143)

排错:
把 SHOW FIELDS FROM `vm_dataforradarshow` 语句放到sql中执行,也报错。这个 vm_dataforradarshow 是一个视图,忽然想起来,视图是有权限的。
里面会包含了是哪个用户创建的,并且在执行视图的时候会用这个用户去执行,结果用户昨天被删掉了,自然执行失败。备份脚本也备份失败。
(因为用的阿里云rds,也怀疑过用户权限问题,创建了一个高权限账号(相当于root),也是备份失败。)

之前遇到的一个问题:
测试环境数据库是user1账户,创建视图也是用user1去创建的。
到正式上,是一个独立的普通用户,比如user2,结果导入sql脚本一直失败,具体错误提示忘记了。
只要把sql脚本里,视图中的user1修改成user2才解决。

避免:
1、开发过程中尽量避免视图使用,毕竟要多耗费一次时间及系统资源。
2、开发测试环境要和正式一致,避免出现我这种账号问题。