Tomcat多实例session共享方案

Tomcat实现多实例session共享的方案还挺多的,up主使用了三种,最终选择了tomcat自带的Cluster集群方案。下面来说一下这三种方案的优缺点。

up主用的tomcat7,至于为什么还是7这么老的版本,因为高版本的对get请求有一些字符校验
另外,这些都是不用改java代码的,其他的没做研究

tomcat-redis-session-manager

这个应该是最常见的方案了,我们随便一搜就是这个,但是代码有些坑。。。

如: 这个 还有这个 等等,还有两个致命的bug,一是session保留时间过长,里面有一段代码 session.setMaxInactiveInterval(getMaxInactiveInterval() * 1000); ,这里多保留了1000倍的时间。二是每次访问都会有一条session记录保留,非常的耗费redis内存。

虽然上述俩bug本up主已经修复了,但是发现还会丢session,估计是redis的驱逐问题,也懒得去调试了。

redisson

本up主发现这个的时候以为终于得救了,看一下人家的官网 https://redisson.pro/ ,还有商业版,就觉得很靠谱。事实证明还是too young too naive啊

因为突然有一天,同事说你这个接口好慢,然后我发现整个机器负载都很高了,访问网站直接卡成狗,看了一下日志,jvm崩溃了 java.lang.OutOfMemoryError: GC overhead limit exceeded

上面那个不管是丢session还是保留时间太长,但是不至于把tomcat搞死。好家伙,这个直接把jvm干崩溃了,OOM可还行

Tomcat Cluster

这里有一个很详细的教程 http://xstarcd.github.io/wiki/Java/tomcat_cluster.html ,我就不赘述了。

注意,我直接贴他的tomcat配置发现有看不见的空行还是啥的,可以去tomcat网站复制。

注意2,一定要在web.xml中添加<distributable />

使用两天了,暂时没发现问题,有待后续观察。

最近的一些感想

最近这一年过的挺快的,对我来说真的是一眨眼的工夫。作为一个住在郊区的打工人,每天固定时间起床、坐地铁、上班、下班、坐地铁、回家、睡觉,一天就这么结束了。日复一日的没有什么差别,所以感觉每天都一个样。要说没差别嘛,其实也有,后面会讲到。好了,也不废话了,下面分解一下,按5部分进行总结一下。

工作

这个其实是最好“处理”的了,特别是对于我这只老社畜来说,不能说如鱼得水吧,只能是游刃有余。(夸张了😂

其实在一家公司待了几年,而且是我这个岗位的来说,事情不多,大多数都是小的需求,基本上都是一周码2-3天就能码完的。剩下的时间就自己安排了,摸鱼、学习新技术等。时间长了也是挺无聊的,也没有太多的挑战(除非突然几个bug一起来😰)

还好薪水能勉强说的过去,不然早就跑路了,感觉待的时间越久越费,现在年龄在这里摆着,也不知道下一份工作如何是好。你们年轻人应该没这些烦恼吧~

生活

人除了睡觉、工作,剩下的时间寥寥无几,也就是我们的生活了。
作为一个有娃的社畜,生活基本上是围绕着娃的,父母、妻子、娃和我自己,这几种元素组成了每天的生活。
生活需要磨合,需要心平气和,需要耐心,需要理解。还是那句话,懂得都懂
这部分就不继续展开讲了,其实就一个字:忍。

学习

这里的学习是宏观上的,不是像学校里那种拿着书本和笔,在教室中的那种,这也是我一直想给身边人普及的一个认知,我们随时都可以学习,活到老学到老。

对于我来说,移植sailfish几乎占据了我在工作、娱乐外的时间,转眼一看我都已经做了4年了,目前也在移植第四台设备,希望能早日有进展。
工作时间的学习,很多是在Java的深度上和Linux的一些盲区,这是一条无止境的路。

娱乐

不得不说,dota2和电影填充了我的娱乐时间,其他的几乎为0。

感情

为什么有了生活部分还有感情部分呢? 我也不知道怎么形容才好,怎么说才会有人懂,但是懂得都懂吧😓

人生就是一座围城,里面的人想出来,外面的人想进去。

结了婚的羡慕谈恋爱的,有娃的羡慕单身没有束缚的,单身的羡慕有男女朋友的,谈恋爱的羡慕…没有,恋爱应该是最美好的。

人一旦到达一个新的阶段,总会想保持现有的,还会努力去够一下新的目标,同时也会有些怀念当初拥有的更“纯粹”的阶段。

如果有那么一个机会、一个时刻,你可以去回到当初那个“纯粹”的阶段,可以出去围城看一看,但是要冒一些风险,理性的我们一般不会去越过这条线,保持自己在围城里面。

但是,这颗种子种下后,它会在你的内心生根发芽。总有一天,这颗种子长大到可以伸出到城墙外面,那时你可以选择砍掉这根树枝,或者狠下心把这颗树彻底根除。

选择,是一个非常有趣的话题。有些人会凭感觉去选,有的人靠计算收益去选择,有的人不做选择,有的人想选择两者。黑客帝国中,尼奥第一次见先知,就探讨过选择的问题。

对错,也是一个非常有趣的话题。何为对,何为错,真的有人能说这件事永远都是对的吗?古人有塞翁失马焉知非福,几千年前的思想家就已经在讨论这个哲学的问题了,自然这个话题是没有答案的。

好了,扯了太多了,夜也深了,该睡觉了。毕竟,明天还要做打工人呢,哪里会有时间思考呢。

水了几天终于水完了,懒得不香写了,就这样吧。

从日志中查询链接文件中的链接是否最近有访问

链接文件a.txt内容如下

1
2
http://example.com/123.txt
http://example.com/456.txt

日志文件为从cdn下载的或者nginx的压缩日志,gz格式

思路:循环zcat压缩文件,然后两个文件都做一个处理,去掉重复的部分,然后对这俩文件进行重复统计,有的话说明链接有访问

简单的示例

1
2
3
4
5
6
7
8
#!/bin/bash
gzs=$(ls |grep gz)
for gz in $gzs;
do
echo "start $gz"
zcat $gz|awk '{print $7}'|sort -n|uniq -c|sort -n > tmp.txt
cat tmp.txt a.txt| sort -n| uniq -c|sort -n |awk '{if($1>1) print $2}' >> exist.txt
done

Gitlab CE使用drbd实现主备方案

痛点

由于Gitlab社区版是不提供高可用等方案的,只能定时备份出来然后出问题了再导入,有时候会丢失数据,而且耗时随着备份文件大小增加,后期维护成本高。

解决思路

在搜索了大量的方案之后,只有使用drbd的才是靠谱的,而且比较容易跟现有的结合,值得尝试。

安装drbd

这里都是参考了 csdn博主的 https://blog.csdn.net/allway2/article/details/102478719


DRBD使用LVM逻辑卷作为后端设备创建XFS文件系统在线添加磁盘扩容操作过程


#### 0.服务器环境信息

drbd1 192.168.111.132 CentOS 7
drbd2 192.168.111.190 CentOS 7


#### 1、禁用SELinux
在两个节点执行: # setenforce 0

##### 永久关闭
可以修改配置文件/etc/selinux/config,将其中SELINUX设置为disabled。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[[email protected] ~]# cat /etc/selinux/config   

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
#SELINUX=enforcing
SELINUX=disabled
# SELINUXTYPE= can take one of three two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted

# sestatus
SELinux status: disabled


关闭firewall:
1
2
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动


设置主机名:

1
2
hostnamectl set-hostname drbd1
hostnamectl set-hostname drbd2


#### 2、安装DRBD

在两个节点执行:
1
2
3
4
5
6
# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# yum install drbd90-utils kmod-drbd90
# lsmod | grep -i drbd
# modprobe drbd
# echo drbd > /etc/modules-load.d/drbd.conf


#### 3、配置DRBD

在两个节点执行:
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
# mv /etc/drbd.d/global_common.conf /etc/drbd.d/global_common.conf.orig
# vi /etc/drbd.d/global_common.conf

global {
usage-count no;
}
common {
net {
protocol C;
}
}


# vi /etc/drbd.d/drbd0.res

resource drbd0 {
disk /dev/drbdvg/drbdlv;
device /dev/drbd0;
meta-disk internal;
on hostname1 {
address 192.168.111.132:7789;
}
on hostname2 {
address 192.168.111.190:7789;
}
}


1
2
3
4
5
6
7
8
9
# pvcreate /dev/sdb
# vgcreate drbdvg /dev/sdb
# lvcreate -l 100%VG -n drbdlv drbdvg
# lvscan
# drbdadm create-md drbd0

# systemctl start drbd
# drbdadm status
# cat /proc/drbd


在主节点执行:
1
2
3
4
5
6
7
8
9
10
# drbdadm primary drbd0 --force

# mkfs.xfs /dev/drbd0
# mount /dev/drbd0 /mnt
# touch /mnt/file{1..5}
# ls -l /mnt/
# df -hT
# vgdisplay
# pvdisplay
# lvdisplay

#### 4、在线扩容
在两个节点执行:
1
2
3
4
5
6
7
8
9
# lsblk
# pvcreate /dev/sdc
# pvdisplay
# vgdisplay
# vgextend drbdvg /dev/sdc
# lvs
# lvdisplay
# lvextend -l+100%FREE /dev/drbdvg/drbdlv
# lvs

等待数据同步完成
1
# watch drbdadm status

在主节点执行:
1
2
3
4
# drbdadm resize drbd0

# xfs_growfs /mnt
# df -hT

扩容完成,等待扩容数据同步完成
# watch drbdadm status

同步完成后可以进行切换测试

在主节点执行:
# umount /mnt/

在从节点执行:
1
2
3
4
5
6
# mount /dev/drbd0 /mnt
# ls -l /mnt/
# df -hT
# touch /mnt/file{11..15}
# ls -l /mnt/
# umount /mnt


在主节点执行:
1
2
# mount /dev/drbd0 /mnt
# ls -l /mnt

应用到Gitlab

如果已经在运行了,那可以在运行的机器上挂载另外一块硬盘,新开一台机器,这俩作为drbd的主备,将运行的gitlab data数据rsync到drbd管理的那块盘上即可

然后改一下gitlab的data位置,重启一下或者reconfigure一下即可。

python使用subprocess查看进程并过滤

来源: https://stackoverflow.com/questions/6780035/how-to-run-ps-cax-grep-something-in-python

将proc1的输出当作proc2的输入来实现

1
2
3
4
5
6
7
8
import subprocess

proc1 = subprocess.Popen(["ps","-ef"],stdout=subprocess.PIPE)
proc2 = subprocess.Popen(['grep', 'mysql'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc1.stdout.close() # Allow proc1 to receive a SIGPIPE if proc2 exits.
out, err = proc2.communicate()
outline = '{0}'.format(out)

使用yavijava创建兼容低版本的虚拟机

痛点

在使用 https://github.com/yavijava/yavijava 创建虚拟机的过程中,默认会将虚拟机的兼容性自动设置为ESXI的版本,如在ESXI 6.5上创建的虚拟机,其兼容性则为 ESXi 6.5 及更高版本 (虚拟机版本 13), 这样导致迁移的时候不能将这个虚拟机迁移到小于ESXI 6.5版本的主机上。

解决

在查询很多资料之后,确认可以通过 https://www.altaro.com/vmware/4-ways-to-downgrade-the-vm-hardware-version/ 文中的方法,将虚拟机先从清单中删掉,更改虚拟机的vmx文件,将virtualHW.version改为需要的版本,重新注册虚拟机即可。

在已知了这些方法之后,进行尝试, 发现在初始化虚拟机之后是无法再进行更改的,只有创建的时候设置好才行,如下即可。

1
2
3
4
5
6
7
8
9
10
11
vmSpec.setVersion("vmx-10"); # 10 表示 esxi 5.5
// call the createVM_Task method on the vm folder
Task task = vmFolder.createVM_Task(vmSpec, rp, null);
String result = task.waitForTask();

if(result == Task.SUCCESS){
System.out.println("VM Created Sucessfully");
}else{
System.out.println("VM could not be created. ");
return;
}

debian,ubuntu无法使用apt下载源数据的解决方法

现象:

不管是默认的源还是ustc的都直接提示 Connection failed,但可以ping通。

1
2
3
4
5
6
7
8
9
10
11
12
13
[email protected]:/# printf "deb http://mirrors.ustc.edu.cn/debian/ buster main contrib non-free\n#deb-src http://mirrors.ustc.edu.cn/debian/ buster main contrib non-free\ndeb http://mirrors.ustc.edu.cn/debian/ buster-updates main contrib non-free\n#deb-src http://mirrors.ustc.edu.cn/debian/ buster-updates main contrib non-free\n#deb http://mirrors.ustc.edu.cn/debian-security/ buster/updates main contrib non-free\n#deb-src http://mirrors.ustc.edu.cn/debian-security/ buster/updates main contrib non-free" > /etc/apt/sources.list
[email protected]:/# apt update
Err:1 http://mirrors.ustc.edu.cn/debian buster InRelease
Connection failed [IP: 202.141.176.110 80]
Err:2 http://mirrors.ustc.edu.cn/debian buster-updates InRelease
Connection failed [IP: 202.141.176.110 80]
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.
W: Failed to fetch http://mirrors.ustc.edu.cn/debian/dists/buster/InRelease Connection failed [IP: 202.141.176.110 80]
W: Failed to fetch http://mirrors.ustc.edu.cn/debian/dists/buster-updates/InRelease Connection failed [IP: 202.141.176.110 80]
W: Some index files failed to download. They have been ignored, or old ones used instead.

解决方法:

更改apt的默认UA

printf 'Acquire\n{\n http::User-Agent "Mozilla/5.0 (Windows NT 5.1; rv:25.0) \nGecko/20100101 Firefox/25.0";\n};' > /etc/apt/apt.conf

参考:

原因:

未知。。。,在另一个网络环境下就可以,也是神奇。

P.S. 感谢公司大数据部门的同学,让我又可以水一篇了 xD (划掉划掉)

Windows使用frp进行远程连接

frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议。

Github介绍: https://github.com/fatedier/frp/blob/master/README_zh.md

安装

从这里https://github.com/fatedier/frp/releases 下载最新的二进制安装包,服务端跟客户端都在一个压缩包里。

服务端

服务端跟客户端都需要一个配置文件,对于服务端配置文件如下

1
2
3
4
5
frps.ini (完整配置文件 https://github.com/fatedier/frp/blob/master/conf/frps_full.ini)
[common]
bind_port = 7000
vhost_http_port = 8888
token = your_token

然后启动只需要一条命令
/usr/bin/frps -c /etc/frps/frps.ini

最好做一下守护,如使用systemd托管

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat /etc/systemd/system/frps.service
[Unit]
Description=frpc daemon
After=syslog.target network.target
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/bin/frps -c /etc/frps/frps.ini
Restart=always
RestartSec=1min
ExecStop=/usr/bin/killall frps
[Install]
WantedBy=multi-user.target

客户端

客户端同服务端也需要一份配置(frpc.ini),如这里我们做windows的远程桌面映射

1
2
3
4
5
6
7
8
[common]
server_addr = 47.98.28.15
server_port = 7000
token = your_token
[rdp]
type = tcp
local_port = 3389
remote_port = 3389

上面的server_addr填写服务端的ip,token同服务端的token。

同样一条命令启动
./frpc.exe -c frpc.ini

做成自启动服务

下载一个nssm.exe放到frp的目录下,然后执行下面的命令(注意下对32、64版本)
nssm.exe install frpc

接下来会弹出一个框,在path处选择启动frpc的frpc.bat

点击Install service即可

启动 nssm.exe start frpc

测试

首先确保你的windows可以被远程连接。

在外网机器输入 47.98.28.15,然后输入你的用户名密码即可连接。

注意开通服务器跟客户端的3389端口,以及服务端的7000,8888端口。

SailfishOS移植到Redmi-5-Plus的一些记录(2)

接上 https://birdzhang.xyz/2018/03/30/SailfishOS%E7%A7%BB%E6%A4%8D%E5%88%B0Redmi-5-Plus%E7%9A%84%E4%B8%80%E4%BA%9B%E8%AE%B0%E5%BD%95/

本文章主要针对 hybris 15.1的移植

挑选设备源码

mer-hybris的android hybris-15.1是基于lineageos的,所以我们在没有官方/非官方lineageos用的时候,也要找基于lineage的第三方rom,如国内的Mokee,国外的OmniROM等,只需要稍微改一点devicetree就可以用了

适配hybris-15.1的一些更改

一、Failed to initialize property area

目前的解决方法是注释掉这个, 还有可能是没有关闭selinux或者没有初始化sailfish所需要的android init rc文件有关

system/core/init/property_service.cpp, 将72行的exit(1);注释掉

二、kernel,device部分

  1. 内核部分主要需要注意的是你的设备是否是有 /vendor分区的,project treble的都会有一个单独的/vendor分区,这个需要注意。

    可以通过这个里查看 arch/arm/boot/dts/qcom/msm8953.dtsi (根据你自己cpu来区分,找不到的话就用grep找一下)

    如下,可以看到有vendor跟system分区单独挂载,这个地方可以看谷歌对system-as-root的说明便于理解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    firmware: firmware {
    android {
    compatible = "android,firmware";
    fstab {
    compatible = "android,fstab";
    vendor {
    compatible = "android,vendor";
    dev = "/dev/block/platform/soc/7824900.sdhci/by-name/cust";
    type = "ext4";
    mnt_flags = "ro,barrier=1,discard";
    fsmgr_flags = "wait";
    status = "ok";
    };
    system {
    compatible = "android,system";
    dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
    type = "ext4";
    mnt_flags = "ro,barrier=1,discard";
    fsmgr_flags = "wait";
    status = "ok";
    };

    也可以通过device tree的 fstab.qcom 查看,如果没有,需要加上去(至少在vince上面是这样,因为后面的dhd要靠这个来判断),如我的需要加这两行

    1
    2
    /dev/block/bootdevice/by-name/system            /system                 ext4    ro,barrier=1                                                    wait,recoveryonly
    /dev/block/bootdevice/by-name/cust /vendor ext4 ro,barrier=1 wait,recoveryonly

    有的设备/dev/block/bootdevice/by-name/system挂载到/下面(对应下面的dhd部分的makefstab_skip_entries),而我的设备/vendor是来自/cust(也是迷 @[email protected]

  1. device tree部分注释掉启用full treble的部分

    如我的设备需要把下面这些注释掉,否则selinux的政策文件会安装到/vendor下面,不会在根目录下产生,sfos需要在根下面有。

    扩展阅读: https://source.android.com/security/selinux?hl=zh_cn

    1
    2
    3
    4
    5
    6
    # Treble
    #BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
    #PRODUCT_FULL_TREBLE_OVERRIDE := true
    #PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE := 27
    #BOARD_VNDK_VERSION := current
    #BOARD_VNDK_RUNTIME_DISABLE := true

三、dhd,dhc部分

https://wiki.merproject.org/wiki/Adaptations/faq-hadk 搜索 15.1也会找到一些需要注意的地方

修改dhd的spec文件,添加

1
2
# On Android 8 the system partition is (intended to be) mounted on /.
%define makefstab_skip_entries / /vendor /dev/stune /dev/cpuset /sys/fs/pstore /dev/cpuctl

也不一定全部要加上,我的设备/system,/vendor就不自动挂载,需要改成这样, 可以先不加然后telnet上去看看这里目录下有没有文件吧

1
%define makefstab_skip_entries /dev/stune /dev/cpuset /sys/fs/pstore /dev/cpuctl

这样会生成system.mountvendor.mount,启动systemd的时候会挂载上

对于有些设备可能提示kgsl kgsl-3d0: |_load_firmware| request_firmware(a530_pm4.fw) failed: -2,需要做一个软链到 /lib/firmware

https://github.com/mer-hybris/droid-config-sony-nile/blob/91c15efb576c29a9d41cc4cd1d40c62ddcce9824/sparse/lib/firmware

调试

暂无很详细的,主要是看dmesg,journalctl等看看把出错的都修了。

通话声音

如果可以打通电话但是没有声音,则需要 pulseaudio-modules-droid-hidl 1.0版本(截止2019-09-24),然后配合新的ril配置文件 https://github.com/mer-hybris/droid-config-sony-nile/tree/master/sparse/etc/ofono

界面crash

看dmesg/logcat/journactl里面是不是有binder的信息,打补丁吧,至于打哪些只能靠猜(大雾