搭建服务器
本地开发完Web App后,只在本地能跑起来是远远未能符合工程应用的需要,我们还需要在服务器上进行账号设置、环境搭建、安装和启动必要的服务、部署自动化、服务进程管理、Web服务设置等的工作,这样才能使我们服务器上的Web在被正常访问的基础上,更高效、稳定地部署和发布。
基本概念
wsgi
- wsgi: (the Python Web Server GateWay Interface) 是一种通信协议
- python web 框架编写的应用程序 <==> 后端服务器之间的通信规范.
- PEP 3333 中描述了 web server 如何与 web application 通信的规范
- 要实现 wsgi 协议,必须同时实现web server 和 web application
- 当前运行在 wsgi 协议之上的web框架有 Bottle, Flask, Django
- uwsgi: 是一种线路协议
- 与wsgi是两种东西,是uWSGI服务器的独占协议
- uWSGI: 是一个web服务器的名字
- uWSGI旨在为部署分布式集群的网络应用开发一套完整的解决方案
- 主要面向web及其标准服务。由于其可扩展性,能够被无限制的扩展用来支持更多平台和多语言
- 实现了WSGI协议、uwsgi协议等
- uWSGI服务器自己实现了基于uwsgi协议的server部分,我们只需要在uwsgi的配置文件中指定application的地址,uWSGI就能直接和应用框架中的WSGI application通信。
- uWSGI的主要特点是:
- 超快的性能
- 低内存占用
- 多app管理
- 详尽的日志功能(可以用来分析app的性能和瓶颈)
- 高度可定制(内存大小限制,服务一定次数后重启等)
Tomcat
运行在JVM之上,绑定IP地址并监听TCP端口的Web服务器。
同时负责:
- 管理Servlet程序的生命周期
- 将URL映射到指定的Servlet进行处理
- 与Servlet程序合作处理HTTP请求——根据HTTP请求生成HttpServletResponse对象并传递给Servlet进行处理,将Servlet中的HttpServletResponse对象生成的内容返回给浏览器
Nginx
轻量级的Web服务器/反向代理服务器/电子邮件(IMAP/POP3)代理服务器/负载均衡服务器
适合偏静态、高并发的场景
可与uWSGI、Tomcat搭配使用
Apache
世界使用排名第一的Web服务器,具有重量级、耗资源、低性能的特点,也具备兼容性强、稳定性高、模块丰富。
一般用于处理数据量大,又需要快速响应的场景
对比Nginx,Apache是同步多进程模型,一个连接对应一个进程,Nginx是异步的,多个连接(万级别)可以对应一个进程
Django内置服务器 + Nginx 部署
Django 内置的服务器软件,可以认为是简化版的 Apache
下面使用阿里云ECS服务器演示(略过购买ECS、购买弹性公网IP、ECS绑定IP的过程)。
修改密码
无论是Linux还是Ubuntu,第一次登录时可能会出现提示Login Incorrect,解决办法是
- 云服务器ECS->实例->选择操作的实例;
- 点击“远程连接”旁边的更多;
- 重置一次密码(可能需要手机短信验证),注意这里的密码修改的不是6位数字那个远程连接的密码,而是root账户的密码;
- 密码修改成功后,必须手动重启一次实例;
- 等待重启成功后,再次连接到远程,输入 root 和 刚刚修改过的密码(密码不明文显示),就可以正常登录了。
远程连接
有两种方式连接,一是通过阿里云上提供的网页版命令行连接,而是本地命令行上ssh连接。
网页版连接时需要注意与本地的输入方式差异,一般通过下图右上角的”复制命令输入“完成,因为页面使用部分字母作为快捷方式,故无法直接输入这些字母。
本地命令方式下,可以使用客户端ssh的id公钥代替输入密码来登录远程主机,步骤如下
$ ssh-keygen -t rsa //创建公钥及秘钥对,默认路径为~/.ssh/id_rsa
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@xx.xx.xx.xx //把公钥复制到远程主机
& ssh root@xx.xx.xx.xx -p port//登录
软件更新
apt-get的应用
apt-get主要用于自动从互联网的软件仓库中搜索、安装、升级、卸载软件或操作系统。
sudo apt-get update //更新本机中的软件包的数据库缓存
sudo apt-cache search <name> //查找包含部分关键字的软件包
sudo apt-get install <package_name> //安装指定的软件(自动安装依赖),-d 只下载包,不解压安装
apt-get install package=version //安装指定版本
apt-get source <source_code_name> //下载软件包源代码
apt-get remove packagename //卸载软件,同时会卸载依赖,但保留配置,--purge 删除配置
apt-get clean //清理所有的缓存文件
dpkg -l //查找安装在机器上面的软件包
python3的安装
sudo apt-get install python3 //安装python3.6,可指定3.7,系统默认有python2
python3 -V //查看python3的版本号
sudo apt-get install pip3 //安装对应3.6的版本,3.7可使用sudo python3.7 get-pip.py
虚拟py环境搭建
pip3 install virtualenv
mkdir awesome-python3-webapp
virtualenv venv -p python3
source venv/bin/activate
(venv)# pip install aiohttp
(venv)# pip install jinja2
cd awesome-python3-webapp
...
git init
git add .
git commit -m "Initial commit"
git remote add origin <remote_url>
git push -u origin master
同步文件
从本地同步到远程
rsync -avz -e ssh /Path/to/uploadFile root@xx.xx.xx.xx:/Path/to/file //使用默认端口
rsync -avz -e 'ssh -p 61124' /Path/to/uploadFile/ root@xx.xx.xx.xx:/Path/to/file //指定端口
从远程同步到本地
rsync -avzP -e ssh root@xx.xx.xx.xx:/Path/to/downloadFile /Path/to/file
rsync -avzP -e 'ssh -p 61124' root@xx.xx.xx.xx:/Path/to/downloadFile /Path/to/file
开放端口
查看端口
使用 lsof 命令来查看某一端口是否开放,例:
lsof -i:80
如果有显示说明已经开放了,如果没有显示说明没有开放
是否在监听端口,例:
netstat -aptn
netstat -nupl (UDP类型的端口)
netstat -ntpl (TCP类型的端口)
开放端口
“实例”->”更多”->”网络和安全组”->”安全组配置”->”(安全组列表)配置规则”->”添加安全组规则”
一般只需设置入规则方向、TCP协议、端口范围、默认权对象(0.0.0.0/0)
检测
在远程主机上使用以下指令检测是否能访问
curl <ip>:<port> //或者使用 wget <ip>:<port>
若出现Connection refused的错误
netstat -tnl
配置数据库
mysql:
下载完注意保存默认提供的密码。
修改密码
mysqladmin -u root password [password]
设置环境变量
$ cd ~
$ vim ./.bash_profile
> export PATH=$PATH:/usr/local/mysql/bin
$ source ~/.bash_profile
$ echo $PATH
在系统设置->MySQL->打开服务
登入
$ mysql -u root -p
$ mysql -uxxx -hx.x.x.x -pxxx -P8066 # 远程登录
重置密码
> SET PASSWORD FOR ['username']@['host']=PASSWORD('[newPassword]');
创建账号
> CREATE USER '[username]'@'[host]' IDENTIFIED BY '[password]';
删除账号
> DROP USER '[username]'@'[host]';
授权
> GRANT [ALL] ON [databasename].[tablename] TO '[username]'@'[host]'
取消授权
> REVOKE [ALL] ON [databasename].[tablename] FROM '[username]'@'[host]'
查询及创建库/表
#显示数据库列表:
>show databases;
#选择使用某个数据库:
>use [databaseName];
#创建数据库:
>create database [databaseName];
#显示库中的数据表:
>show tables;
#显示数据表的结构:
>describe [tableName];
#建表:
create table 表名 (字段设定列表);
#删库和删表:
drop database 库名;
drop table 表名;
#将表中记录清空:
delete from 表名;
#显示表中的记录:
select * from 表名;
卸载
$ sudo rm /usr/local/mysql
$ sudo rm -rf /usr/local/var/mysql
$ sudo rm -rf /usr/local/mysql*
$ sudo rm ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
$ sudo rm -rf /Library/StartupItems/MySQLCOM
$ sudo rm -rf /Library/PreferencePanes/My*
$ subl /etc/hostconfig`
# Remove the line MYSQLCOM=-YES-
$ rm -rf ~/Library/PreferencePanes/My*
$ sudo rm -rf /Library/Receipts/mysql*
$ sudo rm -rf /Library/Receipts/MySQL*
$ sudo rm -rf /private/var/db/receipts/*mysql*
linux下开启、关闭、重启mysql服务命令
若启动应用时,报链接不到mysql的错误(Can’t connect to MySQL server on ‘x.x.x.x’),可检查以下几点:
- 输入”service mysqld status”查看mysql服务是否已启动;
- 查账号是否存在,且是否已授权给对应表
use mysql; select host,user from user;
; - 账号密码是否正确
mysql -u username -p passwd
- 允许任何主机登陆MySQL,设置
/etc/mysql/mysql.conf.d/mysqld.cnf
bind-address=0.0.0.0 和 port=3360; - 关闭防火墙
systemctl stop firewalld
systemctl status firewalld
- 云服务器的安全组开放对应端口3360.
控制mysql服务的操作:
1)启动
- 使用 service 启动:service mysql start
- 使用 mysqld 脚本启动:/etc/inint.d/mysql start
- 使用 safe_mysqld 启动:safe_mysql&
2)停止 - 使用 service 启动:service mysql stop
- 使用 mysqld 脚本启动:/etc/inint.d/mysql stop
- mysqladmin shutdown
3)重启 - 使用 service 启动:service mysql restart
- 使用 mysqld 脚本启动:/etc/inint.d/mysql restart
四、查看mysql状态
mysql
用户管理
创建用户
sudo adduser xx
- xx为用户名
- 会自动创建用户主目录
- 会自动指定系统Shell版本 /bin/bash
- 需用户指定密码
- 自动调用 /etc/adduser.conf
- 自定义参数
- –home 指定主目录
- –quiet 只打印警告和错误信息,忽略其它信息
- –conf 指定configuration文件
- –force-badname 用户名合法性弱检查
方法2
sudo useradd xx
sudo useradd -d /home/xx -m xx
- 什么都不指定
- 自定义参数
- -d 指定主目录
- -m 如果存在不再创建,但是此目录并不属于新创建用户;如果主目录不存在,则强制创建; -m和-d一块使用
- -s 指定用户登录时的shell版本
- -M 不创建主目录
修改密码
sudo passwd xx
删除用户
sudo userdel xx
# 连同主目录一并删除
sudo userdel -r xx
- /etc/passwd 使用者账号资讯,可以查看用户信息
- /etc/shadow 使用者账号资讯加密
- /etc/group 群组资讯
- /etc/default/useradd 定义资讯
- /etc/login.defs 系统广义设定
- /etc/skel 定义档的目录
授权用户
chown -R xx:xx /home/xx
chmod 760 /home/xx
在不同用户间切换执行命令或脚本
$ su - test_user <<EOF
$ echo ~/
$ ls -al
$ EOF
# EOF 可以是其它标识符,表示后续的输入作为子命令或子Shell的输入,直到遇到EOF为止,再返回到主Shell,例如还可以用到 mysql 的SQL语句去,作为跟在mysql账号密码后的语句输入。
进程管理
Supervisor是用Python开发的监控服务进程工具,可以监听、启动、停止、重启一个或多个进程。当一个进程意外被杀死,利用Supervisor监听到进程死后,会自动将它重启,自动恢复,不再需要自己写shell脚本来控制。
1.安装Supervisor:
yum install supervisor
easy_install supervisor
supervisord -v
2.修改配置:安装好后,/etc/supervisor会生成一个supervisord.conf文件及一个conf.d文件目录。supervisord.conf是默认的配置;conf.d中是放指定进程的自定义配置。
conf文件中,使用[xx]分隔开配置中的模块,其中[include]是导入其它自定义的进程配置文件,默认配置是制定.ini的格式,亦可是*.conf。
添加自定义配置,新建一个对应应用名为xx的xx.conf到 /etc/supervisor/conf.d/xx.conf
,写入如下内容
[program:xx]
command = /srv/xx/www/app.py
directory = /srv/xx/www
user = userName
startsecs = 3
redirect_stderr = true
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 10
stdout_logfile = /srv/xx/log/app.log
因为supervisor不能监控后台进程,所以配置中的command 不能为后台运行命令。如果.py文件中不指定执行环境,例如#!/usr/bin/env python3
或#!/srv/xx/venv/bin python3
,那command就需要设置完整的指令 /path/python3 /path/xx.py
执行start之前先指定配置的路径(直接使用supervisorctl可能会报错 unix:///var/run/supervisor/supervisor.sock no such file。执行-c 后也免去了start)
sudo supervisord -c /etc/supervisord.conf
sudo supervisorctl -c /etc/supervisord.conf
supervisord 是启动 supervisor 守护进程(类似于 systemd 或 init.d 这种用于托管进程的服务)。supervisorctl 是 supervisord 的命令行控制台,它的其它操作指令还包括
supervisorctl status #查看所有进程的状态
supervisorctl stop es #停止es
supervisorctl start es #启动es
supervisorctl restart es #重启es
supervisorctl update #配置文件修改后可以使用该命令加载新的配置
supervisorctl reload #重新启动配置中的所有程序
... #es可换成all,管理配置中的所有进程
最后开始监听某进程(当然需要在xx进程已开启的状态下进行)
$ sudo supervisorctl reload
$ sudo supervisorctl start xx
$ sudo supervisorctl status
xx RUNNING pid 1401, uptime 5:01:34
3.遇到的问题
1) 如果执行 start 指令时提示spawn error
,可以查询日志
tail -20 /var/log/supervisor/supervisord.log
Exit code 127 一般意味着找不到指令,对command中的指令添加绝对路径。也可能是配置没重加载成功,可尝试重启supervisord进程(可参考下一点问题解决办法)
2) 如果执行 supervisord -c 时,提示以下错误:
Error: Another program is already listening on a port that one of our HTTP servers is configured to use. Shut this program down first before starting supervisord.
一般是进程已经打开过,杀掉进程重试即可
ps -ef | grep supervisord
kill -s SIGTERM pid
3) 如果执行 start 指令时提示 file is not executable
,则可能是权限问题,修改启动文件的权限 chmod chmod a+x app.py
即可。
配置Nginx
把配置文件xx放到/etc/nginx/sites-available/
目录下(一般是在copy default文件的基础上修改。如果和default监听一样的端口等设置,则需要将default删除,保持一个应用一个配置,其中监听的端口等设置必须各不一样)
server {
listen 80; #监听80端口
root /srv/xx/www;
access_log /srv/xx/log/access_log;
error_log /srv/xx/log/error_log;
# server_name x.xx.com; # 配置域名
# 处理静态文件 /favicon.ico;
location /favicon.ico {
root /srv/xx/www
}
# 处理静态资源
location ~ ^\/static\/.*$ {
root /srv/xx/www
}
# 动态请求转发到9000端口
location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
}
}
然后在/etc/nginx/sites-enabled/目录下创建软链接
sudo ln -s /etc/nginx/sites-available/xx
让Nginx重新加载配置文件,webapp应该就能正常运行
sudo /etc/init.d/nginx reload
sudo service nginx restart # 或通过service重启
nginx既可做正向代理,也可做反向代理(反向代理简单来说,就是像客户端访问80端口,帮你定位到9000端口,这样的转发功能),以上例子中相关的参数如下
- X-Forwarded-For,是用于记录代理信息的,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加在X-Forwarded-For中
- X-Real-IP,只记录真实发出请求的客户端IP
如不想服务器会响应超时,可设
server {
...
client_body_timeout 1w;
}
http {
fastcgi_read_timeout 1w;
fastcgi_send_timeout 1w;
proxy_read_timeout 1w;
proxy_send_timeout 1w;
uwsgi_send_timeout 1w;
uwsgi_read_timeout 1w;
}
其中的参数参考时间单位:
ms milliseconds
s seconds
m minutes
h hours
d days
w weeks
M months, 30 days
y years, 365 days
安装Redis
MacOS
$ wget http://download.redis.io/releases/redis-5.0.0.tar.gz
$ tar xzf redis-5.0.0.tar.gz
$ cd redis-5.0.0
$ make
若make过程提示
…
“_redisAsyncSetDisconnectCallback”, referenced from: _sentinelReconnectInstance in sentinel.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: * [redis-server] Error 1
make: * [all] Error 2
symbol(s) not found for architecture x86_64
可通过卸载brew中的binutils
解决
$ brew uninstall binutils
$ make distclean
$ make
然后继续
$ cd src
$ ./redis-server [../redis.conf]
$ ./redis-cli
redis> set foo bar
OK
redis> get foo
Ubuntu
$sudo apt-get update
$sudo apt-get install redis-server
$ redis-server
$ redis-cli
redis 127.0.0.1:6379> ping
PONG
Django + uWSGI + Nginx
NodeJS + Nginx
node app.js
Apache
查看版本
$ httpd -v
Server version: Apache/2.4.34 (Unix)
Server built: Feb 22 2019 20:20:11
启动 Apache
$ sudo apachectl start
访问服务器
浏览器上访问 http://127.0.0.1 或 http://localhost
站点的根目录为系统级根目录 /Library/WebServer/Documents
停止 Apache
$ sudo apachectl stop
重启 Apache
$ sudo apachectl restart
创建用户级根目录
- 用户目录下创建 Sites,及
touch Sites/.localized
- 检查 username.conf 文件(username为当前用户名),是否存在与/etc/apache2/users,没有则创建,权限设为
sudo chmod 644 username.conf
- 配置username.conf(注意替换username)
<Directory "/Users/username/Sites/">
Options Indexes MultiViews FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
- 编辑
/etc/apache2/httpd.conf
文件,解除以下注释
LoadModule authz_core_module libexec/apache2/mod_authz_core.so
LoadModule authz_host_module libexec/apache2/mod_authz_host.so
LoadModule userdir_module libexec/apache2/mod_userdir.so
LoadModule include_module libexec/apache2/mod_include.so
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
Include /private/etc/apache2/extra/httpd-userdir.conf
- 编辑
/etc/apache2/extra/httpd-userdir.conf
文件,解除以下注释
Include /private/etc/apache2/users/*.conf
- 重启 Apache
- 验证 http://127.0.0.1/~username
参考
wsgi、uwsgi、uWSGI、nginx、apache
使用 supervisor 管理进程
Nginx 配置详解
部署Web App
shell脚本中使用其他用户执行脚本
Get Apache, MySQL, PHP and phpMyAdmin working on macOS Sierra
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 mingfungliu@gmail.com
文章标题:搭建服务器
文章字数:4.3k
本文作者:Mingfung
发布时间:2019-04-06, 00:00:00
最后更新:2022-01-13, 17:29:04
原始链接:http://blog.ifungfay.com/后端/搭建服务器/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。