Main.java内容为:
package com.company;
public class Main {
public static void main(String[] args) {
System.out.println("Hello Java!");
}
}
原始目录结构: com/company/Main.java
cd com/company
javac *.java
得到Main.class, 然后删掉Main.java(否则最终jar包里会有源码)
在com同级创建manifest.txt文件,内容为:
Manifest-Version: 1.0
Main-Class: com.company.Main
注意manifest.txt最后一定要留一个空行, 而且不要用记事本编辑, 最好用notepad++编辑, 因为jar命令不认\r\n换行符
目录结构为:
manifest.txt
com/company/Main.class
在根目录下执行:
jar -cvfm a.jar manifest.txt com (此时会生成a.jar)
java -jar a.jar (此时在控制台打印出:Hello Java!)
512MB内存超低配服务器安装mysql5.7,很容易启动失败,设置swap分区启动成功后,经常被oom-killer杀掉,从以下三个方面减少mysql内存占用。
修改之前先free -h看一下内存使用情况
1. 开启256MB swap内存
free -h
sudo dd if=/dev/zero of=/swapfile bs=1M count=256
sudo mkswap /swapfile
sudo swapon /swapfile
# 这样swap内存就创建成功了,但是重启后会失效
# 永久保存
sudo vi /etc/fstab
# 文件末尾加入这行内容,保存退出
/swapfile swap swap sw 0 0
2. 设置 vm.swappiness = 70 #这个值越大,越积极使用swap分区,相对应的就是越卡,越不容易被oom-killer杀掉
编辑 vi /etc/sysctl.conf , 保存
sysctl -p 加载配置
3. 调整mysql配置
vi /etc/my.cnf
[mysqld]
wait_timeout = 600
interactive_timeout = 600
log_warnings=1
performance_schema=OFF
table_definition_cache=400
table_open_cache=256
保存后重启mysql服务器
都改完之后free -h, 再看一下内存使用情况
1) svn co 报错:
svn: E210007: Unable to connect to a repository at URL 'svn://git.oschina.net/xxx'
svn: E210007: Cannot negotiate authentication mechanism
原因是缺少组件,运行sudo yum install cyrus-sasl cyrus-sasl-plain cyrus-sasl-ldap
问题解决
2) 安装mysql
wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
yum -y install mysql57-community-release-el7-10.noarch.rpm
yum -y install mysql-community-server
systemctl start mysqld.service
systemctl status mysqld.service
chkconfig mysqld on
grep "password" /var/log/mysqld.log
mysql -uroot -pPASSWORD
set global validate_password_policy=0;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpassword';
yum -y remove mysql57-community-release-el7-10.noarch
3) mysql启动失败,需要设置swap内存
free -h
# 创建1G空间
sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
sudo mkswap /swapfile
sudo swapon /swapfile
# 这样swap内存就创建成功了,但是重启后会失效
# 永久保存
sudo vi /etc/fstab
# 文件末尾加入这行内容,保存退出
/swapfile swap swap sw 0 0
4)设置mysql编码为utf8mb4
打开/etc/my.cnf,添加
[mysqld]
character_set_server = utf8mb4
[mysql]
default_character_set = utf8mb4
[client]
default_character_set = utf8mb4
5) 安装python3.6.5
编译环境的安装:yum install zlib-devel bzip2-devel openssl-devel ncurese-devel(要先安装这个不然python安装不完整,会没有pip3)
wget https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgz
tar -xf Python-3.6.5.tgz
cd Python-3.6.5
设置安装目录:./configure --prefix=/usr/bin/python-3.6.5
新建安装的文件夹:sudo mkdir /usr/bin/python-3.6.5
编译命令 :
make(等待..)
安装命令:sudo make install
设置软连接
sudo ln -s /usr/bin/python-3.6.5/bin/python3.6 /usr/bin/python3
# 创建虚拟python3环境
python3 -m venv project-name
cd project-name
source bin/activate
rds = redis.Redis() # 这里用到了redis
# 从收到登录请求开始...
...
# ****** 后台登录次数限制 ******
# 两分钟内只能请求10次, 不同ip不会相互影响,防止被攻击后影响正常用户
cur_timestamp = int(time.time())
timestamp_key = "login_timestamp" + request.remote_addr
times_key = "login_times" + request.remote_addr
if rds.get(timestamp_key) is None:
rds.set(timestamp_key, cur_timestamp, ex=10 * 60)
if rds.get(times_key) is None:
rds.set(times_key, 0, ex=10 * 60)
if cur_timestamp - int(rds.get(timestamp_key)) > 2 * 60:
rds.set(times_key, 1, ex=10 * 60)
rds.set(timestamp_key, cur_timestamp, ex=10 * 60)
else:
if int(rds.get(times_key)) > 10:
return '{"status":%d, "errmsg":"登录太频繁了,请2分钟后重试!"}' % ERR_UNKNOWN
rds.incr(times_key, 1)
# ****** 后台登录次数限制 ******
# 后续验证账户密码匹配等操作...
...
在Ubuntu环境下python默认是2.7版本,而且这个版本是卸载不掉的,uwsgi默认调用的是python2.7,而且uwsgi也没有参数可以指定使用什么python版本,网上查了下说是用插件,研究了半天也没搞明白怎么个用法。偶然发现了一个简单的方法。
python3 -m venv mysite
cd mysite
source bin/activate
我们知道uwsgi + Flask框架,可以实现多进程,多线程。常见线程锁有threading.Lock(),进程锁有multiprocessing.Lock(),但是我在实际测试中发现python原生提供的多进程锁在uwsig + flask多进程多线程环境中并不好用。实测代码如下:
import multiprocessing
import threading
import time
import redis
rds = redis.Redis()
mutex = multiprocessing.Lock()
class MyThread(threading.Thread):
# 大概需要执行3秒钟
def run(self):
for i in range(100):
with mutex:
x = rds.get("lock-test")
time.sleep(0.03)
rds.set("lock-test", int(x) + 1)
@app.route('/run', methods=['GET'])
def run():
t = MyThread()
t.start()
return "run function run."
@app.route('/total', methods=['GET'])
def total():
return str(rds.get("lock-test"))
@app.route('/clear', methods=['GET'])
def clear():
rds.set("lock-test", 0)
return "clear!"
在一个单核CPU的阿里云Ubuntu服务器,我开了4个进程4个线程,uwsgi执行参数如下:
uwsgi --socket 127.0.0.1:9001 --chdir mysite --wsgi-file flask_app.py --callable app --pidfile /home/pidfile.pid --master --processes 4 --threads 4 --enable-threads --lazy-apps --daemonize /home/uwsgi.log
测试方法: 先在浏览器上运行/clear链接,然后运行/run链接若干次(我是用两个浏览器和Postman,几乎同时访问3~5次),然后打开/total链接,每刷新一次数字都有增加,等一会数字稳定了,结果最终数字不是100的整数,说明这个进程锁是错的。
下面我们尝试使用文件锁。
# Not work for windows
import fcntl
class FLock(object):
def __init__(self, lock_file):
self.lock_file = "/tmp/" + lock_file
def require(self):
self.fn = open(self.lock_file, "w")
fcntl.flock(self.fn.fileno(), fcntl.LOCK_EX)
def release(self):
self.fn.close()
mutex = FLock("pis-project")
class MyThread(threading.Thread):
def run(self):
for i in range(100):
mutex.require()
x = rds.get("lock-test")
time.sleep(0.03)
rds.set("lock-test", int(x) + 1)
mutex.release()
发现这样依然有问题,最后total出来的数据也不是100的整数。。。为什么呢? 后来我写了这样一段代码:
# Not work for windows
import fcntl
class FLock(object):
def __init__(self, lock_file):
self.lock_file = "/tmp/" + lock_file
def require(self):
self.fn = open(self.lock_file, "w")
fcntl.flock(self.fn.fileno(), fcntl.LOCK_EX)
def release(self):
self.fn.close()
mutex = FLock("pis-project")
mutex.require()
print("require")
mutex.require()
print("require")
mutex.release()
print("release")
发现竟然能一路跑下来, 恍然大悟,原来我们的文件锁可以锁进程,但无法锁同一个进程里的不同线程。 所以再加一个线程锁,最终版本是这样的:
# Not work for windows
import fcntl
import threading
class FLock(object):
def __init__(self, lock_file):
self.lock_file = "/tmp/" + lock_file
self.thread_lock = threading.Lock()
def require(self):
self.thread_lock.acquire()
self.fn = open(self.lock_file, "w")
fcntl.flock(self.fn.fileno(), fcntl.LOCK_EX)
def release(self):
self.fn.close()
self.thread_lock.release()
这样测试下来,total始终是100的整数,说明我们的锁是正确的。 那能否使用multiprocessing.Lock + threading.Lock 实现需求呢?
import multiprocessing
import threading
class FLock(object):
def __init__(self):
self.thread_lock = threading.Lock()
self.process_lock = multiprocessing.Lock()
def require(self):
self.thread_lock.acquire()
self.process_lock.acquire()
def release(self):
self.process_lock.release()
self.thread_lock.release()
经过测试发现这样是不可以的。我们无法在主进程中创建一个锁,之后在子进程中直接使用。
# 最终可用的版本
import fcntl
import threading
class FLock(object):
def __init__(self, lock_file):
self.lock_file = "/tmp/" + lock_file
self.thread_lock = threading.Lock()
def require(self):
self.thread_lock.acquire()
self.fn = open(self.lock_file, "w")
fcntl.flock(self.fn.fileno(), fcntl.LOCK_EX)
def release(self):
self.fn.close()
self.thread_lock.release()
g_k = FLock("__some_name__")
def g_lock(fp):
def _d(*args, **kw):
try:
g_k.acquire()
r = fp(*args, **kw)
finally:
g_k.release()
return r
return _d
@g_lock
def need_lock_func():
pass