开发者博客 – IT技术 尽在开发者博客

开发者博客 – 科技是第一生产力


  • 首页

  • 归档

  • 搜索

RabbitMQ集群-镜像模式 1 部署说明 2 Rabbi

发表于 2021-06-21

1 部署说明

1.1 环境准备

IP地址 主机名 操作系统 用途 软件版本
192.168.15.12 mq01 Centos 7.8 磁盘节点 rabbitmq-server-3.8.3,erlang-22.3.4,socat-1.7.3.2
192.168.15.13 mq02 Centos 7.8 内存节点

1.2 配置主机和hosts文件

  1. 更改二台mq节点的主机名为mq01,mq02.

[root@mq01 ~]# vim /etc/hostname

mq01 //另一台改为mq02

  1. 然后修改hosts配置文件。

[root@mq01 ~]# vim /etc/hosts

192.168.15.12 mq01

192.168.15.13 mq02

127.0.0.1 mq01 //另一台为127.0.0.1 mq02

::1 mq01 //另一台为 ::1 mq02

1.3 安装基础组件

1.3.1 安装Rabbitmq-server和Erlang

  1. 下载软件包

packagecloud.io/rabbitmq/er…

github.com/rabbitmq/ra…

www.rabbitmq.com/rabbitmq-re…

www.dest-unreach.org/socat/downl…

下载好后上传到当前文件夹

  1. 安装Erlang

yum localinstall erlang-22.3.4-1.el7.x86_64.rpm

  1. 安装Socat依赖

tar zxvf socat-1.7.3.2.tar.gz

cd socat-1.7.3.2

./configure

make && make install

  1. 安装Rabbitmq-server

rpm –import rabbitmq-release-signing-key.asc

yum localinstall rabbitmq-server-3.8.3-1.el7.noarch.rpm

1.3.2 服务管理

  1. 启动服务

systemctl start rabbitmq-server

  1. 把mq01的erlang.cookie拷贝到其他主机

[root@mq01 ~]# scp /var/lib/rabbitmq/.erlang.cookie root@192.168.15.13:/var/lib/rabbitmq/.erlang.cookie

[root@mq01 ~]# scp /root/.erlang.cookie root@192.168.15.13:/root/.erlang.cookie

[root@mq02 ~]# systemctl restart rabbitmq-server

  1. 添加WEB管理服务

/usr/lib/rabbitmq/bin/rabbitmq-plugins enable rabbitmq_management

service rabbitmq-server start

1.4 加入集群

  1. mq02先暂停rabbitmq

​ [root@mq02 ~]# rabbitmqctl stop_app

  1. 将mq02加入集群

[root@mq02 ~]# rabbitmqctl reset

[root@mq02 ~]# rabbitmqctl join_cluster –ram rabbit@mq01

Clustering node rabbit@mq02 with rabbit@mq01

[root@mq02 ~]# rabbitmqctl start_app

  1. 查看集群状态

rabbitmqctl cluster_status

1.5 登录WEB控制台

1.5.1 修改登录配置文件

vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.3/ebin/rabbit.app

​ 将rabbit.app中的{loopback_users, [<<”guest”>>]},改为{loopback_users, []}

systemctl restart rabbitmq-server

1.5.2 登录

打开浏览器输入http://nodeip:15672, 输入默认的Username:guest,输入默认的Password: guest 。

2 Rabbimq镜像集群部署说明

2.1 创建rabbitmq策略

在mq01节点的控制台上创建策略

(1)点击admin菜单–>右侧的Policies选项–>左侧最下下边的Add/update a policy。

(2)Definition设置ha-mode为all,将集群设置为镜像模式

(3)点击Add policy。

clip_image002.jpg
Name: policy的名称

Pattern: exchanges或queue名称的匹配模式(正则表达式)

Definition:镜像定义,包括三个部分ha-mode, ha-params, ha-sync-mode

ha-mode:指明镜像队列的模式,有效值为 all/exactly/nodes

​ all:表示在集群中所有的节点上进行镜像。

Priority:可选参数,policy的优先级

2.2 创建队列

在mq01节点的控制台上添加队列

(1) 点击Queues菜单–>左侧下边的Add a new queue。

(2) 输入参数,点击Add queue。

clip_image004.jpg

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

对接支付宝App支付接口详解

发表于 2021-06-21

前言

因工作需要,这几天摸索了很久,网上查找的资料大多不齐全,不详细,只有部分讲解及代码…所有我准备尽可能的把这篇博客写的详细易懂一些…好了..废话不多说..下面开始!!!

1.集成支付宝app支付,首先去申请一个支付宝账户..
open.alipay.com/platform/ma…
申请完了以后登录 再这里可以看到一个沙箱 看下图

image.png
点击进去

image.png

到这里我们在沙箱环境下的网页工作差不多就做完了…接下来就应该下载ali支付的jar包了..

下载地址:docs.open.alipay.com/54/106370/

下载完成后,添加到你的maven仓库中,如果项目是maven项目,还需要在pom文件中添加

image.png
2.我们需要先看一些支付宝的一些文档.

app支付官方文档地址:docs.open.alipay.com/204

1、参数说明

(1)out_trade_no:商户订单号,由商户自定义设置;

(2)subject:商品标题;

(3)product_code:固定产品码值:QUICK_MSECURITY_PAY;

(4)total_amount:交易订单金额,精确到小数点后2位,最小设置为0.01;

2、接口请求示例

沙箱账号查看地址:openhome.alipay.com/platform/ap…

① controller层

1
2
3
4
5
6
7
8
9
10
11
12
less复制代码/**
* 充值
* @param payDto payDto
* @return R
*/
@PostMapping(value = "/charge")
public R charge(@RequestBody PayDto payDto){
//payDto就是你前端传过来的值,比如充值金额是多少 用户id是多少..
//这个实体类根据你们自己的业务需求去写就好
String orderString = aliPayService.order(payDto);
return R.ok("orderString",orderString);
}

② service层

1
2
3
4
5
6
vbnet复制代码/**
* 支付宝下单
* @param payDto payDto
* @return String
*/
String order(PayDto payDto);

③serviceImpl

重点 重点 重点 重点 重点 重点 重点 请各位仔细阅读这里的每一行代码

首先这里我们先新建一个AlipayConfig实体类代码我贴出来.有些东西需要你们自己修改我会在代码上方注释的..仔细看…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
arduino复制代码package com.wenliao.cloud.config;

/**
* @ClassName: AliPayConfig
* @Description: 需要传给支付宝SDK的公共基本参数
* @author: Linn
* @Date: 2019/4/3 9:22
*/
public class AliDevPayConfig {

/**
* 1.商户appid
*/
public String APPID = "这个就是在沙箱环境下你看到你的appId的那一串数字";

/**
* 私钥 pkcs8格式的
*/
public static String RSA_PRIVATE_KEY ="这个就是我上面说的应用私钥生成 注意这里是私钥";

/**
* 3.支付宝公钥
*/
public static String ALIPAY_PUBLIC_KEY = "这个就是你把生成的应用公钥在沙箱网页哪里输入后,就可以查看到支付宝公钥..把看到的支付宝公钥copy过来放这里就ok";

/**
* 4.服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
//这个着重讲一下..支付完成后,支付宝会通过这个url请求到你的服务端..
//这个url一定是要公网可以访问才行...如果需要测试的话..我后面有讲到..
//这里你可以先写你本地项目的url 例如:localhost:8080/项目名/访问路径
public static String notify_url = "http://2hu4349021.wicp.vip/pay/aliNotify";

/**
* 5.页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
*/
//这里同上..不做详细说明了..
public static String return_url = "http://2hu4349021.wicp.vip/pay/returnUrl";

/**
* 正式环境支付宝网关,如果是沙箱环境需更改成https://openapi.alipaydev.com/gateway.do
*/
public static String URL = "https://openapi.alipaydev.com/gateway.do";

/**
* 7.编码
*/
public static String CHARSET = "UTF-8";

/**
* 私钥 pkcs8格式的
*/
// 8.返回格式
public static String FORMAT = "json";

/**
* //签名方式 加密类型
*/
public static String SIGNTYPE = "RSA2";

上面的代码我写了一些注释..希望大家好好看一下..特别是一些刚刚接触支付宝对接的人..有很大帮助的

接下来我们就是在impl中实现了..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
scss复制代码    @Override
public String order(PayDto payDto) {
//这里你可以做一些存表操作..具体根据你们自己的业务来操作...
String orderString = "";//这个字符串是用来返回给前端的
String orderNo = record.getOrderId();//这行代码是生成一个商户的订单号..根据你们自己的业务需求去生成就可以了..
log.info("==================支付宝下单,商户订单号为:" + orderNo);

try {
AliDevPayConfig aliDevPayConfig= new AliDevPayConfig(); //实例化上面的那个配置类..
//实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
AlipayClient alipayClient = new DefaultAlipayClient(AliDevPayConfig.URL, aliDevPayConfig.getAPPID(),
AliDevPayConfig.RSA_PRIVATE_KEY, AliDevPayConfig.FORMAT, AliDevPayConfig.CHARSET,
AliDevPayConfig.ALIPAY_PUBLIC_KEY, AliDevPayConfig.SIGNTYPE);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
//业务参数传入,可以传很多,参考API
//model.setPassbackParams(URLEncoder.encode(request.getBody().toString())); //公用参数(附加数据)
//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
model.setBody("具体描述信息.例如QQ币充值");
//商品名称
model.setSubject("例:QQ币");
//商户订单号(根据业务需求自己生成)
model.setOutTradeNo(orderNo);
//交易超时时间 这里的30m就是30分钟
model.setTimeoutExpress("30m");
//支付金额 后面保留2位小数点..不能超过2位
model.setTotalAmount(10.00);
//销售产品码(固定值) //这个不做多解释..看文档api接口参数解释
model.setProductCode("QUICK_MSECURITY_PAY");
ali_request.setBizModel(model);
//异步回调地址(后台)//这里我在上面的aliPayConfig有讲..自己去看
ali_request.setNotifyUrl(AliDevPayConfig.notify_url);
log.info("====================异步通知的地址为:" + ali_request.getNotifyUrl());
//同步回调地址(APP)同上
ali_request.setReturnUrl(AliDevPayConfig.return_url);
log.info("====================同步通知的地址为:" + ali_request.getReturnUrl());

// 这里和普通的接口调用不同,使用的是sdkExecute
//返回支付宝订单信息(预处理)
AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(ali_request);
//就是orderString 可以直接给APP请求,无需再做处理。
orderString = alipayTradeAppPayResponse.getBody();
System.out.println(orderString);
} catch (AlipayApiException e) {
e.printStackTrace();
log.info("与支付宝交互出错,未能生成订单,请检查代码!");
}
return orderString;
}

好..到这里就拿到了一个orderString返回给前端..

返回信息:

1
perl复制代码alipay_sdk=alipay-sdk-java-dynamicVersionNo&app_id=2016101800718925&biz_content=%7B%22out_trade_no%22%3A%22201809251015343222843%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%22app%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95%22%2C%22passback_params%22%3A%22%25E5%2585%25AC%25E7%2594%25A8%25E5%259B%259E%25E4%25BC%25A0%25E5%258F%2582%25E6%2595%25B0%25E6%25B5%258B%25E8%25AF%259512334%25EF%25BC%2581%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%7D&charset=utf-8&format=JSON&method=alipay.trade.app.pay&notify_url=http%3A%2F%2F106.14.187.178%2Fopendevtools%2Fnotify%2Fdo%2Fa9bed896-0fc0-4b05-ba55-6a2550cacd36&return_url=https%3A%2F%2Fwww.baidu.com%2F&sign=qiOEfMcQoObzuPdZNkMOzavHfJLskTUWJxb08YObj8D0SexDStOw%2BHEwOs7x1hGih8Zs3rsT%2BA3aYVnmwp0FTnTYHx2cTbvz1tkNTzoguOG%2BdNR4b5dsJ%2BvUU4UbHV2KDOxg%2FASUcjcbhqitYraWjBgL02QWgTa%2FpA7dpZnxaOKyksZ1tvp7dR3zYvfDdVnfo3vpXlJxc8QTXsYvZdpODvmKG9odw%2FTsP2fZdt3Up7aiq7Ae8rby%2FNg%2BIMcGJjH%2F5MnUC99%2FU9%2Bjwt%2Biqt7jwU4PVfGimDY6ifIYs3PosGwfwrMTSZkI8AzdcsmwHRcqGJJNzlzegl9jQHw9mBzSAw%3D%3D&sign_type=RSA2&timestamp=2018-09-25+13%3A09%3A52&version=1.0

客户端调试工具

前端调用支付宝接口进行支付….这里提供一个支付宝的测试App

测试服务端生成的请求参数是否正常,可使用客户端调试工具。

客户端调试工具:openclub.alipay.com/read.php?ti…

显示效果

image.png
注意:未输入密码之前,支付宝订单还是为创建状态,只有输入密码之后,才会生成支付宝订单,所以这个时候用查询接口查询会报错“订单不存在”

到这里支付成功后,支付宝那边会有一个同步返回和异步返回接口

这个同步我暂时还没有弄太明白…同步也只是告诉你,这个订单有没有支付…并不代表支付成功..支付成功还是得看异步通知返回…

controller层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ini复制代码    /**
* 支付宝支付成功后.异步请求该接口
* @param request
* @return
* @throws IOException
*/
@RequestMapping(value="/aliNotify",method= RequestMethod.POST)
@ResponseBody
public String aliNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("=支付宝异步返回支付结果开始");
//1.从支付宝回调的request域中取值
//获取支付宝返回的参数集合
Map<String, String[]> aliParams = request.getParameterMap();
//用以存放转化后的参数集合
Map<String, String> conversionParams = new HashMap<String, String>();
for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext();) {
String key = iter.next();
String[] values = aliParams.get(key);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
conversionParams.put(key, valueStr);
}
System.out.println("==返回参数集合:"+conversionParams);
String status=aliPayService.aliNotify(conversionParams);
return status;
}

service层

1
2
3
4
5
6
javascript复制代码    /**
* 支付宝异步回调
* @param conversionParams conversionParams
* @return String
*/
String aliNotify( Map<String, String> conversionParams);

serviceImpl层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
typescript复制代码/**
* 支付宝异步请求逻辑处理
*
* @param
* @return
* @throws IOException
*/
@Override
public String aliNotify(Map<String, String> conversionParams) {
log.info("=支付宝异步请求逻辑处理=");
//签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
boolean signVerified = false;
try {
//调用SDK验证签名
String alipayPublicKey = AliDevPayConfig.ALIPAY_PUBLIC_KEY;
String charset = AliDevPayConfig.CHARSET;
String signType = AliDevPayConfig.SIGNTYPE;

signVerified = AlipaySignature.rsaCheckV1(conversionParams, alipayPublicKey, charset, signType);
//对验签进行处理.
if (signVerified) {
log.info("+支付宝回调签名认证成功+");
// 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure 支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id)
this.check(conversionParams);
//验签通过 获取交易状态
String tradeStatus = conversionParams.get("trade_status");

//只处理支付成功的订单: 修改交易表状态,支付成功
//只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
if (tradeStatus.equals("TRADE_SUCCESS") ||tradeStatus.equals("TRADE_FINISHED")) {
//TODO 获取支付宝通知完成充值后续业务
//交易成功 获取商户订单号

/**修改订单信息*/

/**余额到账*/
//这里就主要是做你们自己的业务需求了,修改一些表什么的..
}
return "success";
} else {
return "fail";
}
} else{ //验签不通过
log.info("++验签不通过 !++");
return "fail";
}
} catch (AlipayApiException e) {
log.info("+++验签失败 !+++");
e.printStackTrace();
}
return "fail";
}

到这里一整个支付就完了……多注意细节就ok…

如果大家有什么疑问,可以在评论区评论.我看到后会及时回复…有不对的地方请指出..我会及时修改.谢谢~

总结:

1
复制代码遇到新需求和新技术,多看官方文档...基本都能解决问题

另外目前在努力筹备自己的开源博客中,寻一位前端工程师共同完成…谢谢~

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

【性能测试】性能测试基本原则与方法

发表于 2021-06-21

性能测试关键点

  • 评估性能指标——线程tps(可架构给),吞吐量qps(可架构给),错误率(可架构给),平均响应时间(可架构给)
  • 模拟线上数据量
  • 了解接口有没有缓存,有缓存的需要设计每次调接口获取的是不一样的数据

如何评估需要测试的接口线程数?

  • 针对老项目:
+ 系统里查看过去一周(或者一个月)内,接口调用量最高的那一天,然后再找到当天中接口调用量最高的时间点(分钟级别),比如说是在12:10调用量为10000,那么我们再换算为每秒调用量10000/60=166,因此可以确定这个接口tps只要达到166即可满足
  • 针对新项目:
+ 二八定律的算法为 80%的请求 / 20%的时间 \* 冗余系数(冗余系数一般为2-5之间,一般可取3)如金融股票交易app,一般是早上9点到下午3点,7*60*60=25200秒,注册用户1000万,日活差不多100w,80%=80w,80w/25200\*3=95.接口吞吐量是95即可满足

压测实际操作

当确定吞吐量指标,根据指标去压对应的接口:

  1. 压测设置参数:添加线程组,线程数=用户数/10;ramp-up period多少秒内启动所有线程,默认一般是1秒,0就是立即全部启动;循环次数一般写永远,压测个10-30分钟,看报告
  2. 聚合报告:Samples发出的请求数、Average单个Request的平均响应时间(ms)、error错误率、Throughput简称tps,吞吐量,每秒处理的请求数。
  3. 写接口,如果多个接口添加正则表达式,上下接口串联
  4. 关联数据库
    cmd运行: jmeter logFile -o reportPath得到报告

其他性能指标可以参考(blog.csdn.net/ddxkjddx/ar…

性能测试指标对应压测方法:

​ 吞吐量的预估值=考虑用什么方法去进行压测

  • 500以下 JM 注:接口吞吐指标在500以下,JM就能满足
  • 500-5000 JM分布式或者LR
  • 5000以上 中控+多机部署
  • JM分布式:JM上配置参数接口,jenkins配置多台服务器,一台控制机,多台负载机,控制机的密钥加到负载机中;
  • JM+Grafana+Influxdb监控性能参数,内存,cpu占用情况,接口吞吐量(Grafana是普罗米修斯的简化版)
    搭建教程:www.cnblogs.com/uncleyong/p…
    • Linux系统
    • 内存
    • 换页swap空间
1
swift复制代码free -m | sed -n '2p' | awk '{print "used mem is "$3"M,total mem is "$2"M,used percent is "$3/$2*100"%"}'

接口的性能瓶颈怎么查看?

随着tps越来越高,如何评估接口性能qps指标:

  • 软硬件的资源利用情况会越来越高,直到满负载(内存,cpu占用情况)
  • 吞吐量会不断变高,直到达到峰值,下降或企稳
  • 响应时间会慢慢变高,超过吞吐量峰值,响应时间曲线会急剧拉升(因硬件资源满负载,软件接口无法处理超高并发,接口处理速度最后会急剧变慢)

所以:性能指标是吞吐量最高的那个值,响应时间缓慢拉升到急剧拉升的拐点,硬件资源最大,这三者的坐标区域中间,就是性能峰值

怎么做性能优化?

  1. 最简单的加线程,进程
  2. 数据库层面,加索引,加缓存,一些机算上的结果缓存,表数据太多,分表,sql优化
  3. 在有IO(网络IO,磁盘IO)的时候,批量读,写,合并网络请求,减少与单点的交互
  4. 代码更高效的实现,改运算逻辑,如本来以账户维度计算金额,改成以产品维度去计算

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

我试了试用 SQL查 Linux日志,好用到飞起

发表于 2021-06-21

大家好,我是小富~

最近发现点好玩的工具,迫不及待的想跟大家分享一下。

大家平时都怎么查Linux日志呢?
像我平时会用tail、head、cat、sed、more、less这些经典系统命令,或者awk这类三方数据过滤工具,配合起来查询效率很高。但在使用过程中有一点让我比较头疼,那就是命令参数规则太多了,记的人脑壳疼。

那查日志有没有一种通用的方式,比如用SQL查询,毕竟这是程序员都比较熟悉的表达式。

今天分享的工具q,就实现了以写SQL的方式来查询、统计文本内容,一起看看这货到底有什么神奇之处。

搭个环境

q是一个命令行工具,允许我们在任意文件或者查询结果,比如可以在ps -ef查询进程命令的结果集上,直接执行SQL语句查询。

宗旨就是文本即数据库表,额~,当然这句话是我自己理解的,哈哈哈

它将普通文件或者结果集当作数据库表,几乎支持所有的SQL结构,如WHERE、GROUP BY、JOINS等,支持自动列名和列类型检测,支持跨文件连接查询,这两个后边详细介绍,支持多种编码。

安装比较简单,在Linux CentOS环境,只要如下三步搞定,Windows环境更是只需安装个exe就可以用了。

1
2
3
4
5
shell复制代码wget https://github.com/harelba/q/releases/download/1.7.1/q-text-as-data-1.7.1-1.noarch.rpm #下载版本

sudo rpm -ivh q-text-as-data-1.7.1-1.noarch.rpm # 安装

q --version #查看安装版本

官方文档:harelba.github.io/q

语法

q支持所有SQLiteSQL语法,标准命令行格式q + 参数命令 + "SQL"

1
java复制代码q <命令> "<SQL>"

我要查询myfile.log文件的内容,直接q "SELECT * FROM myfile.log"。

1
sql复制代码q "SELECT * FROM myfile.log"

q不附加参数使用是完全没有问题的,但利用参数会让显示结果更加美观,所以这里简单了解一下,它的参数分为 2种。

input输入命令:指的是对要查询的文件或结果集进行操作,比如:-H命令,表示输入的数据包含标题行。

1
sql复制代码q -H "SELECT * FROM myfile.log"

在这种情况下,将自动检测列名,并可在查询语句中使用。如果未提供此选项,则列将自动命名为cX,以c1起始以此类推。

1
SQL复制代码q  "select c1,c2 from ..."
  • output输出命令:作用在查询输出的结果集,比如:-O,让查询出来的结果显示列名。
1
2
3
4
5
sql复制代码[root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H "select count(UID) from - where UID='root'"
104
[root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H -O "select count(UID) from - where UID='root'"
count(UID)
104

还有很多参数就不一一列举了,感兴趣的同学在官网上看下,接下来我们重点演示一下使用SQL如何应对各种查询日志的场景。

玩法贼多

下边咱们一起看几个查询日志的经常场景中,这个SQL该如何写。

1、关键字查询

关键字检索,应该是日常开发使用最频繁的操作,不过我个人认为这一点q并没有什么优势,因为它查询时必须指定某一列。

1
2
3
4
5
shell复制代码[root@iZ2zebfzaequ90bdlz820sZ software]# q "select * from douyin.log where c9 like '%待解析%'"
2021-06-11 14:46:49.323 INFO 22790 --- [nio-8888-exec-2] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9g9uJ6%2F
2021-06-11 14:57:31.938 INFO 22790 --- [nio-8888-exec-5] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9pdhGP%2F
2021-06-11 15:23:48.004 INFO 22790 --- [nio-8888-exec-2] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9pQjBR%2F
2021-06-11 2

而用grep命令则是全文检索。

1
2
3
shell复制代码[root@iZ2zebfzaequ90bdlz820sZ software]# cat douyin.log | grep '待解析URL'
2021-06-11 14:46:49.323 INFO 22790 --- [nio-8888-exec-2] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9g9uJ6%2F
2021-06-11 14:57:31.938 INFO 22790 --- [nio-8888-exec-5] c.x.douyin.controller.ParserController : 待解析URL :url=https%3A%2F%2Fv.douyin.com%2Fe9pdhGP%2F

2、模糊查询

like模糊搜索,如果文本内容列有名字直接用列名检索,没有则直接根据列号c1、c2、cN。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sql复制代码[root@iZ2zebfzaequ90bdlz820sZ software]# cat test.log 
abc
2
3
4
5
23
24
25
[root@iZ2zebfzaequ90bdlz820sZ software]# q -H -t "select * from test.log where abc like '%2%'"
Warning: column count is one - did you provide the correct delimiter?
2
23
24
25

3、交集并集

支持UNION和UNION ALL操作符对多个文件取交集或者并集。

如下建了test.log和test1.log两个文件,里边的内容有重叠,用union进行去重。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sql复制代码q -H -t "select * from test.log union select * from test1.log"

[root@iZ2zebfzaequ90bdlz820sZ software]# cat test.log
abc
2
3
4
5
[root@iZ2zebfzaequ90bdlz820sZ software]# cat test1.log
abc
3
4
5
6
[root@iZ2zebfzaequ90bdlz820sZ software]# q -H -t "select * from test.log union select * from test1.log"
Warning: column count is one - did you provide the correct delimiter?
Warning: column count is one - did you provide the correct delimiter?
2
3
4
5
6

4、内容去重

比如统计某个路径下的./clicks.csv文件中,uuid字段去重后出现的总个数。

1
sql复制代码q -H -t "SELECT COUNT(DISTINCT(uuid)) FROM ./clicks.csv"

5、列类型自动检测

注意:q会理解每列是数字还是字符串,判断是根据实数值比较,还是字符串比较进行过滤,这里会用到-t命令。

1
sql复制代码q -H -t "SELECT request_id,score FROM ./clicks.csv WHERE score > 0.7 ORDER BY score DESC LIMIT 5"

6、字段运算

读取系统命令查询结果,计算/tmp目录中每个用户和组的总值。可以对字段进行运算处理。

1
2
3
4
5
6
sql复制代码sudo find /tmp -ls | q "SELECT c5,c6,sum(c7)/1024.0/1024 AS total FROM - GROUP BY c5,c6 ORDER BY total desc"

[root@iZ2zebfzaequ90bdlz820sZ software]# sudo find /tmp -ls | q "SELECT c5,c6,sum(c7)/1024.0/1024 AS total FROM - GROUP BY c5,c6 ORDER BY total desc"
www www 8.86311340332
root root 0.207922935486
mysql mysql 4.76837158203e-06

7、数据统计

统计系统拥有最多进程数的前 3个用户ID,按降序排序,这就需要和系统命令配合使用了,先查询所有进程再利用SQL筛选,这里的q命令就相当grep命令。

1
2
3
4
5
6
7
8
9
10
11
sql复制代码ps -ef | q -H "SELECT UID,COUNT(*) cnt FROM - GROUP BY UID ORDER BY cnt DESC LIMIT 3"

[root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H "SELECT UID,COUNT(*) cnt FROM - GROUP BY UID ORDER BY cnt DESC LIMIT 3"
root 104
www 16
rabbitmq 4
[root@iZ2zebfzaequ90bdlz820sZ software]# ps -ef | q -H -O "SELECT UID,COUNT(*) cnt FROM - GROUP BY UID ORDER BY cnt DESC LIMIT 3"
UID cnt
root 110
www 16
rabbitmq 4

我们看到加与不加-O命令的区别就是否显示查询结果的标题。

8,连文件查

一般情况下,我们的日志文件会按天分割成很多个固定容量的子文件,在没有统一的日志收集服务器的情况下,如果不给个报错时间区间去查一个关键词,那么无异于大海捞针。

如果可以将所有文件内容合并后在查就会省事很多,q支持将文件像数据库表那样联合查询。

1
sql复制代码q -H "select * from douyin.log a join douyin-2021-06-18.0.log b on (a.c2=b.c3) where b.c1='root'"

总结

看完可能会有人抬杠:q写这么多代码直接用awk不香吗?额~ 介绍这个工具的初衷并不是说要替换现有哪种工具,而是多提供一种更为便捷的查日志方法。

我也有在用awk确实很强大没得说,但这里边涉及到一个学习成本的问题,琳琅满目的命令、匹配规则想玩转还是要下点功夫的。而对于新手程序员稍微有点数据库经验,写SQL问题都不大,上手q则会容易的多。


整理了几百本各类技术电子书,送给小伙伴们。关注公号回复【666】自行领取。和一些小伙伴们建了一个技术交流群,一起探讨技术、分享技术资料,旨在共同学习进步,如果感兴趣就加入我们吧!

电子书地址

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

IO流传输中的图片加密 IO流传输中的图片加密

发表于 2021-06-21

这是我参与更文挑战的第7天,活动详情查看: 更文挑战

IO流传输中的图片加密

1.加密过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
js复制代码package 图片加密_2020;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class PicTest {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
fis = new FileInputStream(new File("怪物万岁.png"));
fos = new FileOutputStream("怪物万岁(加密).png");

byte[] buffer = new byte[20];
int len;
while ((len = fis.read(buffer)) != -1) {
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}
}
1
2
js复制代码            fis = new FileInputStream(new File("怪物万岁.png"));
fos = new FileOutputStream("怪物万岁(加密).png");

fis接收需要加密的图片文件
fos存放加密后文件

1
2
3
4
5
6
js复制代码 while ((len = fis.read(buffer)) != -1) {
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer, 0, len);
}

buffer[i] = (byte) (buffer[i] ^ 5);
关键加密步骤,将buffer中的每一位与5或其他数字异或操作,不经解密程序的操作,得到的图片将不能正常打开。

image.png

2.解密操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
js复制代码package 图片加密_2020;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class jiemi {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
fis = new FileInputStream(new File("怪物万岁(加密).png"));
fos = new FileOutputStream("怪物万岁(解密后).png");

byte[] buffer = new byte[20];
int len;
while ((len = fis.read(buffer)) != -1) {
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

}
}
1
2
js复制代码            fis = new FileInputStream(new File("怪物万岁(加密).png"));
fos = new FileOutputStream("怪物万岁(解密后).png");

fis接收加密后的文件
fos则存放解密后的图片文件

1
2
3
js复制代码  for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}

其中,解密操作再次异或5,根据异或操作的特性可以得到正常的图片内容。

image.png

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

曝光一个网站,我周末就耗在上面了。

发表于 2021-06-21

你好呀,我是why。

刚刚过去的周末你干啥了,是卷起来了,还是躺平了?

我其实是想躺平的,但是无意间发现一个学习的网站,居然被这个网站吸引了,然后就跟着网站卷起来了。

真是一个非常不错的网站,好东西,要大家分享,于是我决定“曝光”一下。

介绍这个网站之前,我先问你一个问题:

Arthas 这个 Java 程序诊断工具,你知道吧?

我相信绝大部分同学都是知道的,但是也有很大一部分同学仅仅是在“纸上谈兵”的阶段而已。

没有自己实际操作过。

为什么呢?

我猜你刚刚知道 Arthas 的时候,肯定是被它各种炫酷的操作、页面给吸引到了。

心想:卧槽,这么 6?


兴致勃勃的准备实操一把,结果一看:需要自己搞个 Demo ,把 Demo 扔到服务器上运行起来,然后在服务器上安装 Arthas,才能分析。

这一套操作对于大部分人来说是没有啥问题的。

但是还是有相当大的一部分同学,都没有一个属于自己的服务器。

巧妇也是难为无米之炊的呀。

第一步就被卡的死死的。

有心实操,奈何条件有限。

于是这事就被搁浅了,放着放着,由于自己没有实操过,关于 Arthas 的各种骚操作也就忘的差不多了。

没有一个趁手的 Demo,没有服务器,没有一个安装好环境的服务器。

这种问题经常出现,也算是学习中遇到的“最后一公里”的问题。

我碰到的这个网站,就是为了解决“最后一公里”这一问题的。

也许它还不够完善,但是至少在 Arthas 上的支持已经是属于无可挑剔了,真正的手摸手教学。

铺垫了这么多,那么网站是啥呢?

就是下面这个网站:

https://start.aliyun.com/


知行动手实验室,是阿里旗下的阿里云弄出来的云原生开源技术体验平台。

它自带运行环境。

使用者只需要关心教程内容本身,无需为繁琐的运行环境准备工作浪费时间。所有实验都在一个事先准备好运行环境的容器中运行。

它具有沉浸式学习体验。

集交互式文档、终端、编辑器三个窗口于一个浏览器页面,无需在多个窗口来回复制粘贴。

它可以一键自动执行命令、代码自动修改。

文档实时可交互,通过鼠标点击即可一键自动执行命令、代码自动修改等操作;也可以选择在终端、编辑器内手动输入查看效果。

我知道,这里的画风看起来很像是一个广告。

但是我发誓,我真的是自来水,真心推荐。


要动手,多动手


知行动手实验室,看这个名字就知道强调的是“行知合一”,是“动手”。

我曾经看到过阿里的一篇名叫《我看技术人的成长路径》的文章。

文章里面提出了一个 721 原创:

70% 做中学,20% 向他人学习,10% 自学

但是实际情况呢,我们不得不承认,大家自学占据了相当大的比重。

而大家自学的时候都有一个通病就是:只看、只想,基本不动手。

关于动手,我印象最深的就是我看这本书的时候:


我记得看这本书的时候,是我刚刚毕业一年多的时候。

当时觉得技术书还挺贵的,还是和同事一起合买的,一人出一半的钱,书放在办公室大家一起看看。

我那个时候一有时间就去翻翻这书。

第一次看的时候感觉:哇塞,这真是一本好书啊。里面全是我不知道的知识点。

但是看完之后,没隔多久,遇到一个问题然后想了半天:呃,这个问题书上好像讲过啊,怎么就想不起来了呢?

于是我就问同事:你是怎么看这个书的呀?我前段时间把书每一页都翻完了,但是现在好多东西都想不起来了。

他告诉我:首先得多看,书中的信息量对你来说还是太大了,看一遍吸收不完全是很正常的。还有,书里面的这么多动手操作的实例,你跟着敲了没?我都操作了一遍,遇到了各种各样的坑。印象自然而然的就深刻了一点。

可谓是一语点醒梦中人,我确实是没有实操过。

不仅没有实操过,甚至一看到实操部分的具体命令,我都是几眼就瞟完了,因为我觉得这部分不重要。

后来我又看了一遍,看这遍的时候,我搞了几个服务器,就跟着书上,把上面的命令都敲了一遍。

进度慢了很多很多,但是吸收的东西也多了很多很多。

过去这么几年了,时至今日,我都记得周末的时候我跑到公司去翻这本书的场景。我都记得我跟着书上搭建集群的时候遇到的各种各样奇奇怪怪的问题。我都记得那 16384 个槽,还有那我怎么也运行不起来的 redis-trib.rb。

我都记得几年以后的一次,面试官问我:你了解 Redis 的集群吗,你自己搭过集群吗?

我当然记得了,毕竟之前那个只有一年经验的小伙子硬着头皮搭集群的时候,心态都被搞崩过数次。


还有近段时间断断续续在看的《MySQL实战45讲》、《MySQL是怎样运行的》、《高性能MySQL》。

里面其实都有大量的实例,特别是 45 讲,好东西呀,老师全是基于案例去讲的。

我看的时候也看的很慢,反正不管懂不懂,先动手开几个窗口,然后把实验的 SQL 准备好,跟着老师一步步的来。

总之,就是要动手。动手,才是学习新技术的不二法门。

做中学,就是动手去做,边做边学。

但是动手的时候大多数时间都是在环境的准备上,导致效率稍微有了那么一点点的低下。

而这个网站,就在部分项目上,解决了这个问题。

知行动手实验室

回到知行动手实验室,带大家一起逛一下这个网站。


说真的,目前这个网站的东西不算特别多,也就是花费了我一个周末的时间研究了一圈。

主要是里面还有一些我不太了解的开源项目,去了解了一下,开拓了一下眼界。

主打的都是阿里生态下的一些技术栈,目前一共有 16 个教程:


可以看到,首先映入眼帘的就是 Arthas 这个诊断工具,毕竟是阿里的亲儿子中比较有出息的一个嘛。

全力推广,不过分。

Arthas 其中分为了四个教程,从入门到实践一应俱全。

接着是 Spring Cloud Alibaba 系列体验:


里面的六个小实验,其中分布式配置、服务注册与发现都是基于 Nacos 做的。 RPC 调用使用的是 Dubbo Spring Cloud、限流与熔断基于 Sentinel、分布式事务使用 Seata、分布式消息基于 RocketMQ。

基本涵盖了微服务开发的主要模块。

算的上是一次完整的体验。

当然了,还有一些其他的 RocketMQ、Dapr、Dubbogo、ChaosBlade、k8s 的实操教程,就不一一解释了。

大家知道目前里面有这些东西就行。

上面提到的大家可能对于 Dapr 和 ChaosBlade 稍微陌生一点。

简单的说一下。

Dapr 的全称是 Distributed Application Runtime,翻译过来就是分布式应用运行时。

它主要是为了云原生而服务的。

应该是属于服务网格中的一种技术,是一种运行时,支持k8s,目的是为了更好的隔离业务,让业务更少的感知中间件等基础建设。

其实与它对标的,应该就是 istio 架构。

需要注意的是 Dapr 是由微软发起的一个开源项目,并不是阿里。

阿里是 Dapr 开源项目的深度参与者和早期采用者,相当于是对于 Dapr 的一个国内大厂背书。

而 ChaosBlade 就是阿里巴巴开源的一款遵循混沌工程原理和混沌实验模型的实验注入工具,帮助企业提升分布式系统的容错能力,并且在企业上云或往云原生系统迁移过程中业务连续性保障。

引用其 git 上的描述:

https://github.com/chaosblade-io/chaosblade/blob/master/README\_CN.md


该项目的生态如下:


目前支持这么多场景:


比如在知行动手实验室里面就有三个实验场景:


总之,关于 ChaosBlade 你就记住一句话:

它是来搞破坏的。给系统或者系统运行的环境注入各种各样的故障,以测试并提升系统的稳定性和高可用性。

在知行动手实验室里面,除了前面提到的官方教程外,它还支持大家自己上传教程。

下面这几种情况就很适合在上面发布教程:

  • 开源、开发者社区在知行发布开源项目入门教程,帮助你的社区用户更好的上手
  • 技术书籍作者在知行发布你的随书实验,弥补技术书籍只能阅读、无法实操的缺陷
  • 培训机构在知行发布的课程先关的教程,配合已有的课程视频,你的学员可以在知行动手实操

你想想,要是我前面提到的《Redis开发与运维》书里面的随书实验能发布到这里,那岂不是美滋滋?

学习效率肯定又高了起来。

教程,是该实验室的一大核心功能。

但是,它还有另外一大功能:


Java 工程脚手架,下面的标语是:

更适合亚太区开发者的 Java 工程脚手架。

虽然我目前还不明白为什么是“更适合亚太区”,但是反正听着就很厉害的样子。


其页面是这样的,是不是很眼熟?

一看就是对标的大家更为熟悉的这个:

https://start.spring.io/


但是通过我的实际使用,我不得不说,还是阿里的脚手架更好用一点。

比如我用阿里的脚手架,搭建的时候选择一个 web 项目的示例代码:


该项目结构如下:


而且这个 web 项目不需要改一行代码,甚至不需要你启动数据库,就能直接运行起来。

因为其使用的 h2 数据库:


运行起来后,访问 h2 控制台如下:


虽然 Demo 项目运行的过程中我发现了几个 bug,但是整体无伤大雅,修改起来也很简单,对于初学者来说,还是很友好的。

在这个页面我还发现了一个叫做 COLA 的项目架构:


COLA 是啥玩意?

https://github.com/alibaba/COLA/


我在官网上拉了一个 COLA 的 Demo,跑了起来,项目结构如下:


官方给了这样的一个代码结构图:


看到这里的时候,我大概明白了,有 App 层、Domain 层、 Infrastructure 层,这个架构其实就是 DDD 思想的一种落地吧。

经过这两天短暂的了解,我发现如果想要理解一下抽象的 DDD 思想,那么 COLA 架构,我感觉是一个不错的切入点。

Arthas 教程

前面介绍了这么多东西,我还是来带着你实操一把,里面的黄金教程:


其实我觉得真的没有这个必要,因为它上面的教程已经是一步步的手摸手教学了。

比如,你看这个 Arthas 基础教程,我给你录个屏幕:


左边是操作文档,右边是运行环境。所及即所得,多香啊。

我是强烈建议你把四个教程都自己去看一遍,操作一把。

但是重心可以放到这个教程里面:


你看看这个教程里面的 14 个实验:


都是实战性的手摸手教学,别人环境、场景、工具都给你准备好了,你只要需要关注于怎么使用这个工具就行了。

比如其中的“Arthas热更新代码案例”,这个其实就是一个生产环境常常会遇到的一个问题:

有一个判断逻辑有问题,我不想修改代码之后,重新打包,然后走上线流程,怎么办?

Arthas 热更新了解一下?

比如,下面的代码:

1
2
3
4
5
6
7
8
复制代码@GetMapping(value={"/user/{id}"})
public User findUserById(@PathVariable Integer id) {
    logger.info("id: {}", (Object)id);
    if (id != null && id < 1) {
        throw new IllegalArgumentException("id < 1");
    }
    return new User(id.intValue(), "name" + id);
}

现在当请求的 id 小于 1 的时候会抛出异常。但是上线之后,我们经过评估发现这个地方也许返回一个默认的值,不抛出异常会更好一点。

那么我们就可以用 Arthas 对这段代码进行热更新。

左边是修改之后,右边是修改之前:


具体怎么去修改,怎么去用 ClassLoader 加载修改之后的代码,这个案例里面都有详细的使用说明:


当然了,如果你要是在实操之后,又再去了解了其热更新背后的工作原理,那么是再好不过的了。

知道了使用方式,掌握了实现原理。恭喜你,再给自己的套一个生产案例,不经意间面试的时候有多了一个加分点。

另外,悄悄的说个骚操作。

你可以随便找个教程,领个窗口,然后……

比如我装个 Redis:


用起来也是不错的:


而且它也支持文件的上传和下载:


诶,反正就是玩嘛。就当熟悉 Linux 命令了。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

PHP转Go 2021年年中总结 做自己的神龙 一起学习

发表于 2021-06-21

时光荏苒,转眼到了6月中旬,是时候总结沉淀一下了。

今天停下来休整,明天才能更快的赶路。

一步一步往前走,踏踏实实的,像龙珠战士们一样,不断修炼,不断变强!

做自己的神龙

86d6277f9e2f0708c223f75485d7629da801f2bd.jpeg

前半年的大事记

  • 北京买房装修
  • PHP转Go
  • 换工作

思考

  • 关于怎么赚更多钱的思考
  • 舍和得
  • 年终目标

PHP转Go

我也算是全栈开发吧,15年入行,入行时做了2年的Android开发,然后在老板的带领下转行做PHP开发,做了3年+,直到今天还在做。

今年过年前工作不是很忙,发现Go是一门非常不错的语言,和我司小天才一起学习Go,学习经历也是非常有意思。

学习Go的过程特意写过一篇来感谢小天才,这里就不赘述了。
有兴趣的同学可以看看这篇文章
回顾一下我的Go学习之旅 | Go 主题月

春节期间我们用Go写了专题活动,Go天生支持高并发的特性比较轻松的给我们抗住了并发压力。

因为春节活动效果很好,元宵节老板又安排我们搞了一波活动。我们趁此机会又把Go语言的应用精进了一步。

之后又利用一个项目机会基于rpc的思想,实现了go和php的互相调用。

实现了新需求,有并发要求的场景使用Go语言实现,已有项目继续使用PHP。

因为对Go的主动学习,也帮助了我拿到新工作的offer。

换工作

目前在新公司已经工作1个月零20天了。

当然了,最近也有朋友问我的新工作怎么样?

看,这就是答案:

image.png

除了累,收获还是蛮大的。

技术的进步主要体现在编程思想的进步,编程习惯的改变.

之前的我是一把solo型选手,受我上任领导影响。他的思想是敏捷开发,用他的话说:“需求一定会改的,所以动手搞就是了,在推进的过程中小步快跑,不断迭代代码。”

但是,我目前领导给我的影响是:“简单的需求当然可以直接上手啦。但是复杂的需求一定要想明白再动手,而且要不断抽象,理解什么是高内聚,不然以后可能很难维护。”

(之前浮于表面,动手多于动脑;目前在强迫自己多动脑筋,多思考,还处在适应阶段。)

对了,我的新领导狠厉害哦。

对我换工作感兴趣的同学可以看看这篇文章,我也不赘述了。
复盘一下后端工程师是如何在一个晚上拿下腾讯T4大佬的~ | 周末学习

更多关于自己进步的总结可以看这篇文章
入职一个月我和腾讯T4大佬都学到了什么 | 周末学习

每篇文章都写点不一样的东西。

下面就是新东西:

买房装修

我是在北京买的房子哦,是不是还挺厉害的,哈哈。

装修真的是一个费心费力的事儿,秉着“高回报”的指导思想。这段艰辛的装修经历除了装修本身以外,我也提高了审美,锻炼了和各种人打交道的能力,讲理的不讲理的人都有。

有了这段经历我才发现,还是做咱们互联网这行的好人多呀,我没选错行业!

后面我准备整理一篇买房及装修踩坑的文章。

src=http___n.sinaimg.cn_front_48_w600h248_20180927_4P4t-hkmwytp3769029.jpg&refer=http___n.sinaimg.jpeg
必须干货输出!

关于怎么赚更多钱的思考

这部分才是干货,我是一个实在人,别光和我谈理想,下面开始谈钱。

我复盘了一下为啥能在北京买房,核心原因在于以下几点:

  • 工作稳定(5年社保未中断,哪怕裸辞过也很快找到了新工作)
  • 赚的不少
  • 花的不多

【工作稳定】是经济基础,这个基础决定了上层建筑,决定了能否有信心在帝都买房付首付,以后每月都要支付不菲的房贷。

【花的不多】不做讨论,我秉承的原则是省小钱花大钱。该花的钱要花,该办的事要办。

重点说一下之前是如何做到【赚的不少】的

首先,基础工资不低,还有绩效考核和年终奖。

其次,自己不懒,在工作之余也会研究一些黑魔法(新技术),结交一些新朋友,接一些私活。

下面重点聊聊接私活这种副业收入的经历和一些思考吧

src=http___pic.51yuansu.com_pic2_cover_00_34_24_5811557241888_610.jpg&refer=http___pic.51yuansu.jpeg

思路的转变

我在最近2年靠接私活大约赚了20万+,接私活完全没有影响我的正常工作哦。

同事们根本感觉不到我在接私活,因为接私活期间丝毫没有影响我本职工作的进度和质量。

有了买房欲望的驱动,改变了我的思路和态度。

当有野心和欲望的时候,动力和效率会明显提高。

私活项目做的基本都是通过朋友介绍的,通过筛选后只做认为比较好的项目。

推进项目的方式基本都是团队协作,我会找靠谱的朋友一起做项目,甚至我会同时驱动不同的团队推进不同的项目。

要做到这点,找到靠谱且合适的人至关重要。

我自己负责擅长的服务端开发和项目管理;产品、设计、客户端、测试会找靠谱的朋友一起做。

在接私活的问题上我是有比较大变化的,我2年前是比较反感接私活的:

原因一是因为当时工作太忙;
二是因为懒,觉得私活也赚不来多少钱,浪费精力。

我是出于什么转变开始接私活的呢?

那段时期我意识到我司的项目已经到了天花板,没有更大的挑战了。

要想学习更新更好的技术,通过商业项目来实践是一个不错的思路,所以我就决定接私活了。

把新的私活项目,用我感兴趣的新技术实现出来。

观念转变之后,我就会比较多的关注一下技术群、运营群、产品群等等,当然还有猪八戒这类平台、也会找朋友主动询问,去找一些比较好的项目。

(绝对不是来者不拒,要有筛选项目的能力。不然很有可能又浪费精力又拿不到尾款)

我做过的一个比较爽的项目是去年疫情期间,在家里和朋友一起搞的小程序项目。时间大约2个月,费用大约8万左右。不仅赚到了快钱,还趁此机会非常较系统的使用了laravel新版本的新特性。

我有个朋友得知我这个经历之后说:“那你干嘛不辞职接私活?能赚的这么多!比在公司上班赚的还多呢。”

我思考这么搞肯定是不稳妥的:

首先:不是总能接到合适的私活

其次:这种私活赚的快钱毕竟是小钱,因为能找个人做私活的项目肯定不是大项目,都是从0到1的小项目。

最后:这类小项目是没有机会做类似高并发这种复杂场景的,技术提升有限,只能重复CRUD。

发愁啊,虽然接私活能在一定程度上应用和熟悉新技术,但是技术进步仍然有限。

那后续的出路在哪里呢?

舍得舍得,有舍才有得。

有了这段经历之后,我认为只有苦练内功,去大厂或者比较大的公司去锻炼,提高自己的编程能力,从短平快的工作方式转型去解决高精尖的技术难点问题。

比如解决类似高并发这种比较复杂的业务场景,才是多赚钱最简单有效的途径。

接私活这种小技,不是长久之计。

那么如何学习、应用、沉淀新技术呢?

我觉得做社区分享是个不错的思路。

关于技术社区的思考

能讲出来让别人理解且认可的技术点,自己一定是掌握了的。

关于掘金这类技术社区的分享,我秉承的观点是:

自己做总结的同时,分享给社区,社区给到我及时反馈。我能更有动力持续输出,持续沉淀总结,持续正向循环。

互联网的圈子除了同事,同学,其他大部分信息来源基本都来自于社区。

今年的一个重大改变就是从社区知识的消费者,也变成了社区信息的生产者。

从被动输入,到主动输出的改变。这种改变还是很爽的。

创作不难,持续高质量创作才难。

src=http___bpic.588ku.com_element_origin_min_pic_19_06_15_77d5c4ca6baef1db0d6bf8bb5538b6c2.jpg&refer=http___bpic.588ku.jpeg

给年终立个flag

  • 苦练内功:掌握高并发的解决方案、掌握K8S的使用、熟练使用Go语言、采用合理的方案重构已有项目:比如rpc+php+go

2021的下半年,只求耕耘,不问收获。把赚钱看的淡一点,把内功看的重一点。

掘金的兄弟们,好好搞,一起进步,奥利给!

一起学习

公众号:程序员升级打怪之旅

微信号:wangzhongyang1993

福利🧧:点这里–>半价买掘金小册,额外领红包

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Redis是如何进行持久化的--AOF和RDB两种方式助你起

发表于 2021-06-21

这是我参与更文挑战的第21天,活动详情查看: 更文挑战


相关文章

Redis实战汇总:Redis实战


前言

Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以 Redis 提供了持久化功能 !

一. RDB(Redis DataBase)

①首先我们进入服务器找到dump.rdb文件:

在这里插入图片描述

②测试触发rdb操作:vim打开redis.conf配置文件

在这里插入图片描述

为了方便测试,我们将其改为 :

1
bash复制代码save 60 5  #意思是在60秒内进行了5次操作,即写入rdb文件中进行持久化保存

如下图所示:

在这里插入图片描述

③触发机制:

1、save的规则满足的情况下,会自动触发rdb规则,测试如下:

先手动删除dump.rdb文件,实验触发规则!

在这里插入图片描述

在Redis中操作5次命令!

在这里插入图片描述

查看是否生成dump.rdb文件!

在这里插入图片描述

成功!

2、执行flushall命令,也会触发rdb规则

再次删除dump.rdb文件!

在这里插入图片描述

执行flushall操作命令!

在这里插入图片描述

正常生成成功!

在这里插入图片描述

3、退出Redis,也会触发rdb规则

删除:

在这里插入图片描述

退出:

在这里插入图片描述

生成成功!

在这里插入图片描述

④恢复rdb文件

1、只需将备份的rdb文件放在我们的redis启动目录即可,Redis启动的时候会自动检查dump.rdb文件并恢复其中的数据!

2、查找文件位置的命令:

1
2
3
java复制代码127.0.0.1:6379> config get dir
1) "dir"
2) "/usr/local/bin" # 如果在这个目录下存在 dump.rdb 文件,启动就会自动恢复其中的数据

⑤优缺点:

优点:

1、适合大规模的数据恢复!

2、对数据的完整性要求不高!

缺点:

1、需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改数据就没有的了!

2、fork进程的时候,会占用一定的内容空间!

⑥总结:

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的。
这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。我们默认的就是RDB,一般情况下不需要修改这个配置!

在生产环境我们会将这个文件进行备份!

二. AOF(Append Only File)

①Redis默认使用的是RDB模式,所以需要手动开启AOF模式!

在这里插入图片描述

十分简单!将no改为yes即可!

重启服务器!

在这里插入图片描述

发现新文件appendonly.aof!

在这里插入图片描述

②aof文件内容:

先进行一些添加的操作:

在这里插入图片描述

然后我们可以vim打开appendonly.aof文件看看里面是什么?

在这里插入图片描述

有木有发现,里面存储的就是我们先前操作的命令!

③修复aof文件:

1、如果有个坏蛋 将我们的aof文件给修改了,加了点乱七八糟的东西,我们该如何修复呢?如下图所示:

在这里插入图片描述

2、重启下Redis看看:发现重启失败!报错配置信息加载失败!

在这里插入图片描述

3、我们可以使用redis-check-aof文件来进行修复!

1
bash复制代码redis-check-aof --fix appendonly.aof  #修复appendonly.aof文件

返回修复成功!

在这里插入图片描述

4、我们再看看aof文件里面的内容!

在这里插入图片描述

5、细心的同学可能会发现虽然错误的内容少了,但是正确的也有一定的丢失!所以这个修复无法做到百分百修复!但是丢弃一小部分和丢失全部,傻子也知道选择哪个吧!哈哈啊!

6、再次重启试试!成功!

在这里插入图片描述

④AOF重写规则!

aof默认的就是文件的无限追加,文件会越来越大!在配置文件中可以设置文件的大小!

在这里插入图片描述

解释:

1
2
3
4
5
6
7
8
bash复制代码# appendfsync always # 每次修改都会 sync。消耗性能 
appendfsync everysec # 每秒执行一次 sync,可能会丢失这1s的数据! # appendfsync no # 不执行 sync,这个时候操作系统自己同步数据,速度最快!

appendfilename "appendonly.aof" # 持久化的文件的名字
appendonly no # 默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分所有的情况下, rdb完全够用!

auto-aof-rewrite-percentage 100 #写入百分比
auto-aof-rewrite-min-size 64mb #写入的文件最大值是多少,一般在实际工作中我们会将其设置为5gb左右!

⑤优缺点!

优点:

1、每一次修改都同步,文件的完整性会更加好!

2、每秒同步一次,最多会丢失一秒的数据!

3、从不同步,效率最高的!

缺点:

1、相对于数据文件来说,aof远远大于 rdb,修复的速度也比 rdb慢!

2、Aof 运行效率也要比 rdb 慢,所以我们redis默认的配置就是rdb持久化!

⑥总结:以下来自伟大的网友总结!

1、RDB 持久化方式能够在指定的时间间隔内对你的数据进行快照存储

2、AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以Redis 协议追加保存每次写的操作到文件末尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。

3、只做缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化

4、同时开启两种持久化方式

  • 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
  • RDB 的数据不实时,同时使用两者时服务器重启也只会找AOF文件,那要不要只使用AOF呢?建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的Bug,留着作为一个万一的手段。

5、性能建议

  • 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留 save 900 1 这条规则。
  • 如果Enable AOF ,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了,代价一是带来了持续的IO,二是AOF rewrite 的最后将 rewrite 过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上,默认超过原大小100%大小重写可以改到适当的数值。
  • 如果不Enable AOF ,仅靠 Master-Slave Repllcation 实现高可用性也可以,能省掉一大笔IO,也减少了rewrite时带来的系统波动。代价是如果Master/Slave 同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个 Master/Slave 中的 RDB文件,载入较新的那个,微博就是这种架构。

路漫漫其修远兮,吾必将上下求索~

如果你认为i博主写的不错!写作不易,请点赞、关注、评论给博主一个鼓励吧~hahah

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

IDEA好用插件推荐 1Git Commit Templa

发表于 2021-06-21

这是我参与更文挑战的第5天,活动详情查看:更文挑战

本篇文章推荐一些好用的idea插件。

1.Git Commit Template

没有安装这个插件之前,使用IDEA提供的Commit功能提交代码:

git1.jpeg

使用了这个插件之后是下面这样的,提供了一个commit信息模板的输入框:

git2.jpeg

完成之后的效果是这样的:

git3.jpeg

2.FindBugs-IDEA

使用方法很简单,就是可以对多种级别的内容进行finbugs

find1.PNG

分析完之后会有一个视图进行提示,详细的说明是哪种问题。

find2.PNG

按照提示解决完问题之后再执行findbug查看情况即可。

3.GsonForma

实际开发中,常常需要json格式的内容转成Object,GsonFormat这款插件可以实现该功能。
自定义个javaBean(无任何内容,就一个空的类),复制你要解析的json,然后alt+insert弹出如下界面 或者,使用快捷键 alt+s,通过快捷键调出该插件

json1.png

格式化json

json2.png

json3.png

惊悚.png

生成如下

json5.PNG

4.CodeGlance:代码微型地图

提供一个代码的微型地图,当你的类比较多的时候可以帮忙你快速定位到要去的位置。这个插件在日常做普通开发的时候用处不大,不过,在你阅读源码的时候还是很有用的,如下图所示:

微型地图.PNG

5.SequenceDiagram:一键生成时序图

一个必备的一个IDEA插件,非常实用。我一般用它来生成简单的方法时序图,方便我们阅读代码,特别是在代码的调用层级比较多的时候。
使用方法很简单,选中方法名(注意不要选类名),然后点击鼠标右键,选择 Sequence Diagram选项即可!

时序图1.jpeg

配置完一些基本的选项比如调用深度之后,我们点击ok即可!在上面这张图中我们已经生成了调用方法之间的时序图。

时序图2.jpeg

时序图生成完成之后,你可以选择导出为图片或者text文件,你还可以通过生成的时序图来定位到相关的代码,这对于我们阅读源码的时候尤其有帮助!

6.GrepConsole

过滤筛选出来自己想看的日志,可以设置颜色

配置好各级日志的前景色

GrepConsole1.jpeg

效果如下
GrepConsole2.jpeg

7.Alibaba Java Coding Guidelines

阿里巴巴 Java代码规范插件。安装该插件后,代码超过 80 行、手动创建线程池等,这些和《手册》中的规约不符时,IDEA中会给出警告提示。建议大家一定一定一定要安装该插件,它会帮助你检查出很多隐患,督促你写更规范的代码。
阿里1.PNG

在编写代码的同时进行提示

阿里2.PNG

8.Java Stream Debugger

Stream 非常好用,可以灵活对数据进行操作,但是对很多刚接触的人来说,不好理解。
那么 Java Stream Debugger 这款神器的 IDEA 就可以帮到你。它可以将 Stream 的操作步骤可视化,非常有助于我们的学习。

stream1.png

stream2.png

9.Rainbow Brackets:彩虹括号

由于很多人没有养成好的编码风格,没有随手 format 代码的习惯,甚至有些同事会写代码超过几百行,阅读起来将非常痛苦。痛苦的原因之一就是找到上下文,由于括号太多,不确定当前代码行是否属于某个代码块,此时这个插件就会帮上大忙。

括号.PNG

10.Auto filling Java call arguments

开发中,我们通常会调用其他已经编写好的函数,调用后需要填充参数,但是绝大多数情况下,传入的变量名称和该函数的参数名一致,当参数较多时,手动单个填充参数非常浪费时间。该插件就可以帮你解决这个问题。安装完该插件以后,调用一个函数,使用 Alt+Enter 组合键,调出 “Auto fill call parameters” 自动使用该函数定义的参数名填充。

11.Material Theme UI

对于很多人而言,写代码时略显枯燥的,如果能够安装自己喜欢的主题将为开发工作带来些许乐趣。
IDEA 支持各种主题插件,其中最出名的当属 Material Theme UI。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

作为一个后端,你应该会的最基本的运维技巧(四)~

发表于 2021-06-20

这是我参与更文挑战的第5天,活动详情查看: 更文挑战


一、Ubuntu服务器使用docker容器安装nginx并且配置其反代让外部可访问

1.使用docker安装nginx

1
sql复制代码docker search nginx

显示如下:
安装nginx
2.下载nginx

1
复制代码docker pull nginx

显示如下:
下载nginx
说明一哈:如果需要下载指定版本的nginx,需要在后面跟上版本号,如果不加版本号,默认为最新版本。

3.查看是否安装成功

1
复制代码docker images

显示如下:
安装成功效果图
显示以上效果就证明安装成功啦!接下来我们来启动docker并且配置。

4.首先建立html、conf、logs文件夹

1
css复制代码mkdir -p{html,conf,logs}

显示如下:
建立文件夹
1)html 作为我们访问入口,文件放在此目录下外部即可访问。
2)conf 配置文件,里面配置了nginx的一些挂载
3)logs 日志,运行docker时会生产日志,方便后期调试和修改

5.将docker的配置文件上传到conf文件目录下,利用scp命令来上传:
blog.csdn.net/weixin_4382…

配置文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
ini复制代码# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;


server {
listen 8081;
root /etc/nginx/html;
location / {
proxy_pass https://www.qycloud.com.cn/api2/user/login/logindata;
}
}
server {
listen 8981;
root /etc/nginx/html;
location / {
proxy_pass https://www.qycloud.com.cn/api2/user/login/logindata;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name www.zxhtom.store;
root /usr/share/nginx/html;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
root /usr/share/nginx/html;
index index.html;
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

upstream pic{
server 182.254.161.54:8088 weight=5;
server 182.254.161.54:8089 weight=5;
}

}

6.启动docker

1
bash复制代码docker run -d -p 80:80 --name dyjnginx -v /opt/soft/nginx/html:/usr/share/nginx/html -v /opt/soft/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /opt/soft/nginx/logs:/var/log/nginx nginx

解析:
1)docker run 启动docker
2)-d 后台启动
3)-p 80:80 将容器的 80 端口映射到主机的 80 端口
4)-v /opt/soft/nginx/html:/usr/share/nginx/html
———将我们自己创建的 www 目录挂载到容器的 /usr/share/nginx/html
5)–name dyjnginx 将docker容器命名为dyjnginx

7.查看docker端口

1
css复制代码docker ps -a

显示如下:
显示如下
8.接下来我使用了scp命令将一个静态页面上传到html目录下,然后输入ip地址及路劲访问,效果如下:
效果图

9.重启docker容器

1
复制代码docker restart container-name

以上就是配置docker的全部内容啦~


点赞收藏加关注不迷路哦~

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

1…637638639…956

开发者博客

9558 日志
1953 标签
RSS
© 2025 开发者博客
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%