如何解决kafka Response Heartbeat The group is rebalancing, so a rejoin is needed导致重复调用eachMessage函数

1
2
[Nest] 19 - 06/16/2021, 1:09:12 PM [ClientKafka] ERROR [Connection] Response Heartbeat(key: 12, version: 3) {"timestamp":"2021-06-16T13:09:12.779Z","logger":"kafkajs","broker":"kafka-0.kafka-headless.dev.svc.cluster.local:9092","clientId":"reviews-ts-service-client","error":"The group is rebalancing, so a rejoin is needed","correlationId":1241,"size":10} +2857ms
[Nest] 19 - 06/16/2021, 1:09:12 PM [ClientKafka] ERROR [Runner] The group is rebalancing, re-joining {"timestamp":"2021-06-16T13:09:12.779Z","logger":"kafkajs","groupId":"reviews-consumer-ts-customer-client","memberId":"reviews-ts-service-client-453b2860-fdab-4c01-aa98-e015667b8d3b","error":"The group is rebalancing, so a rejoin is needed","retryCount":0,"retryTime":330} +1m

其实这个报错非常恶心人,如果是入库等程序一般不会遇到,但是如果是请求网页的进程,很容易就遇到了,然后就会心跳超时,之后就会重启消费者,重新执行eachMessage函数,但是之前的eachMessage函数依然在执行,会导致eachMessage越来越多然后卡死。

1
2
https://github.com/nestjs/nest/issues/7270
https://github.com/tulios/kafkajs/issues/1097

这里是两篇遇到这个问题的文章,第一个解决的方法是
HOW TO RESOLVE THIS ISSUE?

1
2
3
sessionTimeout: 60000,
heartbeatInterval: 40000,
maxWaitTimeInMs: 43000,

sessionTimeout : it should be greater than the processing time of method.
heartbeatInterval : someone said, it should 2/3 of sessionTimeout
maxWaitTimeInMs : it must be _greater with heartbeatInterval

This issue was resolved by above configuration.

也就是增加会话时间。
其实也不需要说第二个文章了,直接说答案,就是增加会话时间和心跳间隔,将这两个增加一定程度,就会避免遇到这个问题了。

现在看日志是非常的舒服,不像以前那样一堆问题。

参考内容:

Options

1
2
3
4
5
6
7
8
9
10
11
12
13
14
kafka.consumer({
groupId: <String>,
partitionAssigners: <Array>,
sessionTimeout: <Number>,
rebalanceTimeout: <Number>,
heartbeatInterval: <Number>,
metadataMaxAge: <Number>,
allowAutoTopicCreation: <Boolean>,
maxBytesPerPartition: <Number>,
minBytes: <Number>,
maxBytes: <Number>,
maxWaitTimeInMs: <Number>,
retry: <Object>,
})
optiondescriptiondefault
partitionAssignersList of partition assigners[PartitionAssigners.roundRobin]
sessionTimeoutTimeout in milliseconds used to detect failures. The consumer sends periodic heartbeats to indicate its liveness to the broker. If no heartbeats are received by the broker before the expiration of this session timeout, then the broker will remove this consumer from the group and initiate a rebalance30000
rebalanceTimeoutThe maximum time that the coordinator will wait for each member to rejoin when rebalancing the group60000
heartbeatIntervalThe expected time in milliseconds between heartbeats to the consumer coordinator. Heartbeats are used to ensure that the consumer’s session stays active. The value must be set lower than session timeout3000
metadataMaxAgeThe period of time in milliseconds after which we force a refresh of metadata even if we haven’t seen any partition leadership changes to proactively discover any new brokers or partitions300000 (5 minutes)
allowAutoTopicCreationAllow topic creation when querying metadata for non-existent topicstrue
maxBytesPerPartitionThe maximum amount of data per-partition the server will return. This size must be at least as large as the maximum message size the server allows or else it is possible for the producer to send messages larger than the consumer can fetch. If that happens, the consumer can get stuck trying to fetch a large message on a certain partition1048576 (1MB)
minBytesMinimum amount of data the server should return for a fetch request, otherwise wait up to maxWaitTimeInMs for more data to accumulate.1
maxBytesMaximum amount of bytes to accumulate in the response. Supported by Kafka >= 0.10.1.010485760 (10MB)
maxWaitTimeInMsThe maximum amount of time in milliseconds the server will block before answering the fetch request if there isn’t sufficient data to immediately satisfy the requirement given by minBytes5000
retrySee retry for more information{ retries: 5 }
readUncommittedConfigures the consumer isolation level. If false (default), the consumer will not return any transactional messages which were not committed.false
maxInFlightRequestsMax number of requests that may be in progress at any time. If falsey then no limit.null (no limit)
rackIdConfigure the “rack” in which the consumer resides to enable follower fetchingnull (fetch from the leader always)

自己用了一天感觉还是没啥卵用,于是又找了一个新的方法,就是把重试次数调低,默认是5次。

因为我们的程序是等待时间长,而不是停止了,所以在心跳间隔没有发送心跳,那么就会重启,但是不会将之前的给关闭。那么我们直接不让他重启就可以了,这个我觉得最好是应该在重新平衡的时候将之前的eachMessage关闭,这个样子就不会有这样的问题了。

Read file error: Error: EISDIR: illegal operation on a directory, read

微信小程序反编译遇到Read file error: Error: EISDIR: illegal operation on a directory, read怎么办?

这个其实就是反编译分包的时候用的bingo.bat文件,我们应该使用node wuWxapkg.js进行反编译。

node wuWxapkg.js -s=主包位置 分包

然后就可以将分包反编译出来了,之后把分包的内容复制到主包的文件夹中就可以了。

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
node wuWxapkg.js -s=chuanjiabing\wxc73957a752500ee8 chuanjiabing\wxc73957a752500ee1.wxapkg
Unpack file chuanjiabing\wxc73957a752500ee1.wxapkg...

Header info:
firstMark: 0xbe
unknownInfo: 0
infoListLength: 630
dataLength: 1546517
lastMark: 0xed

File list info:
fileCount: 13
Saving files...
Unpack done.
now dir: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1
param of mainDir: chuanjiabing\wxc73957a752500ee8
sub package word dir: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\indexPages
real mainDir: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8
Split app-service.js and make up configs & wxss & wxml & wxs...
deal js ok
deal sub html ok
Decompile ./indexPages/home/index.wxml...
Decompile success!
Decompile ./indexPages/thread/comment/index.wxml...
Decompile success!
Decompile ./indexPages/thread/index.wxml...
Decompile success!
Decompile ./indexPages/thread/post/index.wxml...
Decompile success!
Decompile ./indexPages/thread/selectAt/index.wxml...
Decompile success!
Decompile ./indexPages/thread/selectPayment/index.wxml...
Decompile success!
Decompile ./indexPages/thread/selectProduct/index.wxml...
Decompile success!
Decompile ./indexPages/thread/selectRedpacket/index.wxml...
Decompile success!
Decompile ./indexPages/thread/selectReward/index.wxml...
Decompile success!
Decompile ./indexPages/thread/selectTopic/index.wxml...
Decompile success!
Decompile ./indexPages/thread/voteEditor/index.wxml...
Decompile success!
splitJs: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\indexPages\app-service.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/common.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/home/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/comment/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/post/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/selectAt/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/selectTopic/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/selectProduct/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/selectRedpacket/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/selectReward/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/selectPayment/index.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8 indexPages/thread/voteEditor/index.js
Splitting "E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\indexPages\app-service.js" done.
Guess wxss(first turn)...
Regard E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8\indexPages\thread\selectProduct\index.wxss as pure import file.
Import count info: {"./indexPages/common.wxss":11}
Guess wxss(first turn) done.
Generate wxss(second turn)...
Generate wxss(second turn) done.
Save wxss...
saveDir: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee1\chuanjiabing\wxc73957a752500ee8

微信小程序反编译

微信小程序反编译

需要使用到的工具wxappUnpacker,node.js

其中wxappUnpacker关注公众号Kisger的工作台,并回复wxappUnpacker即可获取下载地址。

首先将wxappUnpacker(以下简称wx)解压缩,然后输入npm install将对应的node.js模块下载下来。

之后我们需要利用到的是wuWxapkg.js这个文件,当然也可以使用bingo.bat。

然后我们打开

C:Users用户名DocumentsWeChat FilesApplet,找到小程序的包。

然后将他复制到wx的文件夹中,输入node wuWxapkg.js xxxx.wxapkg即可将小程序反编译出来。

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
E:\work\study\littleprogram>bingo.bat chuanjiabing\wxc73957a752500ee8.wxapkg

E:\work\study\littleprogram># WXAPPUNPACKER_PATH 项目路径
'#' is not recognized as an internal or external command,
operable program or batch file.

E:\work\study\littleprogram>set WXAPPUNPACKER_PATH=E:\work\study\littleprogram\

E:\work\study\littleprogram>set FILE_FORMAT=wxapkg

E:\work\study\littleprogram>echo "node E:\work\study\littleprogram\/wuWxapkg.js "
"node E:\work\study\littleprogram\/wuWxapkg.js "

E:\work\study\littleprogram>node E:\work\study\littleprogram\/wuWxapkg.js chuanjiabing\wxc73957a752500ee8.wxapkg
Unpack file chuanjiabing\wxc73957a752500ee8.wxapkg...

Header info:
firstMark: 0xbe
unknownInfo: 0
infoListLength: 734
dataLength: 2313578
lastMark: 0xed

File list info:
fileCount: 19
Saving files...
Unpack done.
Split app-service.js and make up configs & wxss & wxml & wxs...
deal config ok
deal js ok
deal wxss.js ok
deal css ok
=======================================================
这个小程序采用了分包
子包个数为: 4
=======================================================
Decompile ./base.wxml...
Decompile success!
Decompile ./comp.wxml...
Decompile success!
Decompile ./custom-wrapper.wxml...
Decompile success!
Decompile ./pages/index/index.wxml...
Decompile success!
splitJs: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8\app-service.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 common.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 discuzq.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 runtime.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 taro.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 vendors.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 app.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 comp.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 custom-wrapper.js
E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8 pages/index/index.js
Splitting "E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8\app-service.js" done.
Guess wxss(first turn)...
Import count info: {}
Guess wxss(first turn) done.
Generate wxss(second turn)...
Generate wxss(second turn) done.
Save wxss...
saveDir: E:\work\study\littleprogram\chuanjiabing\wxc73957a752500ee8
Split and make up done.
Delete files...
Deleted.

File done.
Total use: 6.399s

通过node.js+python实现蓝奏云上传服务

1. cookie获取

首先是cookie,这个想必大家都知道,我们登录一个网站后,再次访问如果不需要输入密码的话,那么就是cookie的帮助了.所以我们如果需要上传文件,那么就需要使用cookie.

1.2 获取

既然cookie这么重要,那么应该怎么获取呢?大多数的网站,都是通过客户端发送账号密码到服务器,然后服务器返回set-cookie,之后客户端根据set-cookie设置cookie,之后每次访问该网站的时候,都会把cookie传入.这样就不需要输入账号密码登录了.
但是这里有人会问,为什么有的网站登录一段时间后就需要重新登录呢?这里就需要说到cookie的时效性了,cookie大多数的网站都不是永久登录的,可能是浏览器关闭就失效,可能是1天失效,还有可能是30天等等.
这里简单看一下php的setcookie函数

1
setcookie(name,value,expire,path,domain,secure)
参数描述
name必需。规定 cookie 的名称。
value必需。规定 cookie 的值。
expire可选。规定 cookie 的有效期。
path可选。规定 cookie 的服务器路径。
domain可选。规定 cookie 的域名。
secure可选。规定是否通过安全的 HTTPS 连接来传输 cookie。

所以,cookie获取不是一次性就可以的,需要根据时间来获取.那么应该怎么获取呢?
目前其实就三种方法:

  1. 自己登录然后打开f12,选择Network,刷新网页,然后找到网站的请求(一般第一个),找到request headers内的cookie,然后就可以使用了.
  2. 通过逆向,获取账号密码加密的参数,之后模拟请求获取cookie
  3. 通过puppeteer/playwright/selenium等库模拟登录获取cookie

目前其实应该就这三种方法,其中1最简单,但是麻烦.2最方便但是难,所以我们选择3.
通过模拟浏览器进行cookie的获取.这里我们使用的是puppeteer.
如果只是单纯使用puppeteer模块的话,是不行的,这应该是会对浏览器指纹进行判断,所以我们这里要用到的是puppeteer-extra这个库.
通过puppeteer-extra这个库,我们可以让浏览器像正常的浏览器一样使用.之后再登录即可.

然后蓝奏云登录有一个滑动验证,这里也有两个方法可以通过,一个是模拟滑动,一个是通过JavaScript滑动,我比较倾向于模拟滑动.

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
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
(async ()=>{
let browser = await puppeteer.launch({
headless: false,
args: [
`--proxy-server=127.0.0.1:7890`,
"--disable-gpu",
"--no-sandbox",
"--disable-setuid-sandbox",
],
})
let page = await browser.newPage();
await page.goto('https://pc.woozooo.com/');
await page.waitForTimeout(1000);
await page.click(".y6");
await page.waitForTimeout(1000);
await page.type("#username", "123");
await page.type(".pwd", "123");
await page.waitForTimeout(1000);
const btn = await page.$('.nc_iconfont.btn_slide');
let box = await btn.boundingBox();
await page.mouse.move(box.x+5, box.y+5)
await page.mouse.down()
await page.mouse.move(box.x+70, box.y+3, {steps: 30})
await page.mouse.move(box.x+150, box.y+5, {steps: 30})
await page.mouse.move(box.x+250, box.y+2, {steps: 30})
await page.mouse.up()
await page.waitForTimeout(1000);
await page.click("#s3");
await page.waitForTimeout(1000);
console.log(await page.cookies())
console.log(await page.title());
await browser.close();
})()

1.3 使用

我们可以将cookie保存到文件中,然后通过python的with open读取该文件,然后发送请求即可.

2. 上传

上传这里我使用的是python,其实只用node.js也可以,或者只用python.
我们要用到的一个是requests库,一个是requests_toolbelt库,其中requests_toolbelt库是为了对文件进行处理,可以通过post将数据传递到服务器上.

1
2
import requests
from requests_toolbelt import MultipartEncoder
1
2
3
4
5
6
7
8
9
10
url = "https://pc.woozooo.com/fileup.php"
headers = {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
"cache-control": "no-cache",
"pragma": "no-cache",
"referer": "https://pc.woozooo.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
}

url为蓝奏云上传文件到服务器的php网址,我们只需要向它传值即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
m = MultipartEncoder(
fields={
"task": "1",
"ve": "2",
"id": "WU_FILE_5",
"name": "名字",
"type": "application/pdf",
"lastModifiedDate": "Fri Mar 18 2022 22:31:14 GMT+0800 (中国标准时间)",
"size": "42671023",
"folder_id_bb_n": "-1",
"upload_file": ("文件名", open("文件名", 'rb'), 'application/octet-stream'),
}
)
headers['Content-Type'] = m.content_type
res = requests.post(url, headers=headers, proxies=proxies, data=m)
print(res.text)

这样,我们就可以将文件上传到蓝奏云服务器上了,但是node.js和python怎么整合到一块使用呢?

Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" environment variable wa

最简单的方法就是cd/node_moudle/puppeteer 然后npm run install即可.
千万不要设置环境变量
PUPPETEER_SKIP_DOWNLOAD=true npm install puppeteer
因为你设置了他会跳过,只需要进入puppeteer路径,进行安装就可以了.

再就是安装后可能会报错.需要安装几个包才可以使用.

1
/home/work/node_modules/puppeteer/.local-chromium/linux-856583/chrome-linux/chrome: error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory

解决:yum install atk

1
chrome: error while loading shared libraries: libatk-bridge-2.0.so.0: cannot open shared object file: No such file or directory`

解决:yum install at-spi2-atk

1
chrome: error while loading shared libraries: libxkbcommon.so.0: cannot open shared object file: No such file or directory

解决:yum install libxkbcommon-x11-devel

1
chrome: error while loading shared libraries: libXcomposite.so.1: cannot open shared object file: No such file or directory

解决:yum install libXcomposite

1
chrome: error while loading shared libraries: libgtk-3.so.0: cannot open shared object file: No such file or directory`

解决:yum install gtk3

根据报错安装对应的包即可.

linux node使用puppeteer的二三事

不断的把写好的项目部署到服务器进行测试,每一次都要重新对服务器进行配置,非常的烦。

在我的日常使用中,发现一个非常致命的问题,就是newPage会冻结。用通俗的话来表示那么就是会卡死。

这样是非常影响进度的,因为你不知道他会什么时候卡死,如果是正好下班的时候,卡死了,那么只有等到第二天上班才能重新启动,这就令人非常烦躁。

然后本来其实我是以为是服务器配置不行,所以启动的进程少一点就可以了,然后自己测试了一下发现貌似就是这样,但是这个时候https://github.com/towry/n/issues/148看到了一篇这个,说是chrome版本的问题,如果是这样的话,那么我们更换一下版本不就行了吗。

文章所写的chrome版本https://chromium.cypress.io/linux/stable/84.0.4147.89然后把他download下来。

其实文章写的是最新版的或者是他说的这个版本都可以,我首先是先试了一下最新版(应该是),我直接apt-get install chromium-browser下载,然后更改puppeteer的启动路径为/usr/bin/chromium-browser(大概是这个路径)然后启动,这里启动我是减少了一定的nodejs文件,然后运行了几个小时,发现确实没啥问题,然后就把所有的文件都加上了,发现出现问题了。依旧会在newPage的时候卡死。

那么接下来尝试一下他说的这个版本,从网站上download下来,然后传到服务器上,tar解压缩,然后修改文件位置,这里发现报错了,不能启动,缺少配置文件。。。。。。。

然后试了大多数的文章所写的方法,没有效果。
后来找到了这篇https://frugalisminds.com/how-to-setup-puppeteer-in-centos-7/

1
yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc

然后再启动就可以了,当然这个安装命令是centos的,不过其实将yum更换成apt-get就能在Ubuntu上安装了,之后就是正常的启动了,不过我没有测试大量文件,可以自己测试一下。