Linux

Linux

Linux目录结构

Linux_第1张图片

Linux操作

命令 解释
磁盘命令
pwd 显示当前在哪个目录
clear 清屏
ls 查看目录(-a 显示全部、-l列表形式)
ls -al 展示所有("d"开头目录、"-"文件、"|"链接)
cd .. 切换到上一层
cd / 切换到系统根目录
cd ~ 切换到用户主目录
cd - 切换到上一个所在目录
cd etc 进入当前目录下得etc
cd ../root 进入当前上一级目录
文件操作
touch 创建文件命令
echo "内容" > a.txt 添加内容到文件,会覆盖
echo "内容" >> a.txt 添加内容到文件中,追加尾部
cat 文件 显示文件内容
cat a.txt >> b.txt a文件追加到b文件
echo $变量 显示变量的值
文件夹操作
mkdir 名称 创建名称的目录
mv a.txt b.txt 移动文件a.txt 并改名为b.txt
mv test tmp 移动test到tmp
cp a.txt b.txt 复制a到b内
cp -r ./web/* ./test 把web下所有文件及子目录复制到test下
rm a.txt 删除当前文件,会询问
rm -f a.txt 直接删除不会询问
rm -rf ./test/* 递归删除test下所有内容
find / -name 'java' 查询java
find / -name '*redis' 查找包含redis的
目录权限
chmod u=rwx,g=rw,o=r a.txt 修改文件权限
chmod 750 -R 文件递归授权
chmod 777 -R 文件目录递归授权
文件内容浏览
cat a.txt 查看a.txt文件全部内容
cat a.txt >> b.txt 把a.txt文件输出到b.txt中
more 文件名 分页查看文件内容
less 文件名 分页查看文件内容(-N 显示行号、-m百分比)退出是Q
head 文件 查看文件头部
tail -f 文件名 实时线持续查看文件内容
文件内容编辑
vim 文件名 进入查看文件
文件内命令
Esc切换模式 命令模式、编辑模式、底行模式
dd 删除改行
yy 复制当前行
p 粘贴
ctrl-f 整页翻页
i、o、a、insert 进入编辑模式
wq 底行模式下写入并退出
q! 退出不保存
wq! 强制保存并退出
set nu 显示行号
set nu! 取消显示行号
:数字 定位行号
/字符 搜索字符(n是下一个、shfit N上一个)
noh 清楚高亮
压缩命令
tar -zcvf test.tar.gz test 将test目录打成压缩包,压缩后文件没那个为test.tar.gz
tar -xvf test.tar.gz 将test.tar.gz进行解压
tar -xvf test.tar.gz -C /usr/local 解压缩到指定目录
zip -r mydata.zip mydata 压缩mydata目录
zip -r ab.zip a b.txt 把a文件夹和b.txt压缩成为ab.zip
unzip -d /a/b filename.zip 将文件解压到/a/b目录内
ps -ef 显示所有进程
kill -9 进程id(PID) 结束进程
grep [option] 匹配正则或者字符串
ifconfig 查看本机网络信息
ping 查看连接状态
netstat 查看本机使用的端口号

Linux软件安装

源码安装

linux软件都是用C/C++程序开发,所谓源码安装,是直接提供程序源代码,需要自行编译,然后生成目标可执行程序。类似提供的.java文件,需要自己编译.class,然后打包为jar,然后运行。源代码形式的特点:操作复杂、编译时间长、极易出现问题、依赖关系复杂,比较适合于专门做linux系统开发的人员。

  1. 绝大多数开源软件都是直接以原码形式发布的

  2. 源代码一般会被打成.tar.gz的归档压缩文件

  3. 源代码需要编译成为二进制形式之后才能够运行使用

  4. 源代码基本编译流程:

1).configure 检查编译环境;

2)make对源代码进行编译;

3)make insall 将生成的可执行文件安装到当前计算机中

RPM安装

RPM 是 LINUX 下的一种软件的可执行程序,你只要安装它就可以了。这种软件安装包通常是一个RPM包(Redhat Linux Packet Manager,就是Redhat的包管理器),后缀是.rpm。RPM是Red Hat公司随Redhat Linux推出了一个软件包管理器,通过它能够更加轻松容易地实现软件的安装。

  1. 安装软件:执行rpm -ivh rpm包名,如:rpm -ivh apache-1.3.6.i386.rpm

  2. 升级软件: 执行rpm -Uvh rpm包名。

  3. 卸载安装: 执行rpm -e rpm包名。

  4. 查询软件包的详细信息:执行rpm -qpi rpm包名

  5. 查询某个文件是属于那个rpm包的:执行rpm -qf rpm包名

  6. 查该软件包会向系统里面写入哪些文件:执行 rpm -qpl rpm包名

一般使用步骤如下:

rpm –i software.rpm(安装);
rpm -e software.rpm(卸载);
rpm –U software.rpm(升级形式安装);
rpm –ivh http://www.linuxcast.net/software.rpm(支持通过http\ftp协议形式安装)

rpm软件包形式的管理虽然方便,但是需要手工解决软件包的依赖关系。很多时候安装一个软件安装一个软件需要安装1个或者多个其他软件,手动解决时,很复杂,yum可以轻松解决这些问题。

YUM安装

yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的软件包管理器,简单理解Yum是rpm的前端程序。它能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。

yum仓库用来存放所有的现有的.rpm包,当使用yum安装一个rpm包时,需要依赖关系,会自动在仓库中查找依赖软件并安装。仓库可以是本地的,也可以是HTTP、FTP、nfs形式使用的集中地、统一的网络仓库。

其特点总结如下:

  1. 自动解决依赖关系

  2. 可以对rpm进行分组,基于组进行安装操作

  3. 引入仓库概念,支持多个仓库

  4. 配置简单

常规使用如下:

# yum install 安装;
# yum remove卸载;
# yum update 升级制定软件

本地安装

把需要的软件下载到linux主机,在主机上直接本地安装

安装软件介绍

服务/软件 端口 备注
jdk8 - JAVA的编译和运行环境
mysql/mariadb 3306 持久化关系型数据库
tomcat 8080 服务器
nginx 80 反向代理服务器

scp 命令上传 (命令是在Windows机器或mac机器上执行)

#scp 源码文件路径  目标文件路径
# 把本地文件上传到服务器 (当前Windows系统目录)
scp ./*.* [email protected]:~/soft
# 把远程服务器用户目录/soft下所有文件,下载到本地
scp [email protected]:~/soft/*.* ./

1、安装jdk【rpm安装】

rpm安装,能自动配置环境变量。

1)查看当前linux系统是否已经安装java

输入 rpm -qa | grep java

如果有已经安装的jdk ,需要使用以下命令删除

2) 卸载JDK

rpm -e --nodeps

3)安装jdk

 cd ~/soft
 rpm -ivh jdk-8u181-linux-x64.rpm

4)java -version测试是否成功

  java -version

展示以下内容代表OK

  java version "1.8.0_181"
  Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
  Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

2、安装mysql(mariadb)【yum】

MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB

1)查看CentOS自带的mysql

输入 rpm -qa | grep mysql

2)将自带的mysql卸载

rpm -e --nodeps

3)yum安装

yum -y install mariadb-server

4)启动mysql

systemctl start mariadb

5)设置root密码

注:这只是设置root用户在本机(linux)登录时的密码

mysqladmin -u root password 'root'  

6)进入mysql

mysql -u root -p

备注:输入密码:root

进入到数据库的执行命令行里面了。

7)  进入mysql,并执行下面sql

保证密码和本地一致

下面的话在mysql数据库里面里面执行

  -- 查看当前的数据库
show databases;
  -- 打开mysql
use mysql ;
  -- 查看所有表
show tables;
​
  -- 我们不用ipv6的地址,直接把host改为%,表示所有客户端都可以连接;同时设置密码为root
update user set host='%' ,password=password("root") where user='root' and host = '::1' ;
  -- 刷新后才能生效
flush privileges;

退出数据库命令操作

exit;
  1. 开放端口号

# 开放端口命令
firewall-cmd --zone=public --add-port=3306/tcp --permanent
#重新加载配置
firewall-cmd --reload
  1. 测试远程连接

使用数据库客户端,输入VMIP地址,输入Mysql的用户名和密码,如图

1.使用IDEA数据库客户端插件

2.输入数据库连接信息

3、配置tomcat【解压缩】

项目部署需要tomcat , 配置端口号。

  1. 下面需要使用uzip命令(根据当前系统情况而定,不是必须),先安装

#获取安装列表
yum list | grep zip/unzip
​
#提示输入时,请输入y
yum install zip
​
#提示输入时,请输入y
yum install unzip 

解压tomcat压缩包到 /app 目录下

cd ~/soft
#解压缩到当前
unzip apache-tomcat-8.5.47.zip
#移动到 /usr/local下
mv apache-tomcat-8.5.47 /usr/local/

启动apache-tomcat-8.5.47

 #确保启动文件有可执行权限,先修改权限
chmod 755 /usr/local/apache-tomcat-8.5.47/bin/*.sh
 #启动
/usr/local/apache-tomcat-8.5.47/bin/startup.sh

开放8080端口

# 开端口命令
firewall-cmd --zone=public --add-port=8080/tcp --permanent
#重新加载配置
firewall-cmd --reload

测试tomcat

在浏览器输入:http://192.168.188.128:8080/

安装Git及Maven

1.安装git【源码安装】

cd ~/soft
# 安装依赖环境
yum -y install zlib-devel curl-devel openssl-devel perl cpio expat-devel gettext-devel openssl zlib autoconf tk perl-ExtUtils-MakeMaker
# 解压缩到当前
tar -zxvf git_v2.4.0.tar.gz 
# 进入目录
cd git-2.4.0
# 配置并编译
autoconf
# 检验相关依赖,设置安装路径
./configure --prefix=/usr/local/git
make && make install

默认安装在 /usr/local/bin,把/usr/local/bin放在系统环境变量或当前用户环境变量,操作如下:

路径:/usr/local/git/bin:

vim ~/.bash_profile  #加入系统环境变量
source ~/.bash_profile #加载配置文件
git --version #查看版本

Linux_第2张图片

备注:这个路径一定写在系统路径的前面,可以覆盖系统默认的git。

2.安装maven【解压缩即可】

# 解压缩到/usr/local下
unzip -d /usr/local apache-maven-3.6.3-bin.zip
# 编辑配置文件,把 /usr/local/apache-maven-3.6.3,添加到系统环境变量
vim ~/.bash_profile  #加入系统环境变量
source ~/.bash_profile #加载配置文件
# 查看maven版本
mvn -v

路径:/usr/local/apache-maven-3.6.3

5、安装Nginx 【源码安装】

Nginx* (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日,2011年6月1日,nginx 1.0.4发布。

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

  • 安装前准备

#安装Nginx依赖环境,-y表示所有提示默认选择y
#nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库:
yum -y install pcre pcre-devel  
#nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库:
yum -y install zlib zlib-devel  
#nginx不仅支持http协议,还支持https,所以需要在linux安装openssl库:
yum -y install openssl openssl-devel
# 安装gcc编译环境
yum -y install gcc gcc-c++ autoconf automake make
  • 源码安装

    #解压缩nginx
    tar -xvf nginx-1.14.2.tar.gz 
    #进入nginx目录
    cd nginx-1.14.2
    #安装配置 
    ./configure  
    #编译
    make     
    # 安装就是把可执行文件复制到/usr/loca/nginx下
    make install   
   
> 安装成功之后,就会在/usr/local下多出了一个nginx目录.
   
- 使用Nginx
​
   ```shell
 #进入nginx的sbin目录
   cd /usr/local/nginx/sbin
#在sbin目录下启动
   ./nginx
    #在sbin目录下停止----需要再用
  ./nginx -s stop
  #在sbin目录下重写加载--需要再用
  ./nginx -s reload
  
  #修改端口(默认端口80)---需要再用
  vim /usr/local/nginx/conf/nginx.conf 配置文件
  • 开端口命令

#开放端口
firewall-cmd --zone=public --add-port=80/tcp --permanent
#重新加载配置
firewall-cmd --reload
#查看是否有nginx的线程是否存在
ps -ef | grep nginx
netstat -an -t -u | grep 80

在浏览器输入:http://192.168.188.128/

Linux_第3张图片

6.安装redis数据库 【源码安装】

  • 解压缩redis

    • tar -xvf redis-3.2.9.tar.gz -C /usr/local

  • make命令编译redis的C语言源码

    • 进入解压后的redis目录下的src目录

    • 输入make命令即可

      Linux_第4张图片

      ./redis-server 服务器

      ./redis-cli 客户端

    注意:可以把编译后的可执行程序可移动到自定义目录

    • 在redis 目录下创建bin目录,把编译后的服务器、客户端、配置文件copy到此目录下

      • cd /usr/local/redis-3.2.9

      • mkdir bin

      • cp ./src/redis-server ./bin

      • cp ./src/redis-cli ./bin

      • cp ./redis.conf ./bin

  • 启动redis服务器

    # 进入bin目录
    cd bin
    # 启动
    ./redis-server
  • 其它指令和配置

    #1. 后台运行 指令后面带 & 代表后台运行
    ./redis-server &  
    #2. 运行远程访问 
    #   使用vi编辑,打开redis.conf文件 (以下是在配置文件中修改)
    #==============
    # 注释如下这行,目前仅运行127.0.0.1访问
    bind 127.0.0.1
    #  开启密码访问模式
    requirepass pass
    # 开启守护进程,允许redis可以后台启动
    daemonize yes
    #===============
    #3. 指定配置文件,启动redis    
    ./redis-server redis.conf 
    ​
    #4. 启动redis客户端和关闭服务器
    ./redis-cli
    ./redis-cli shutdown
    #5.开放端口
    firewall-cmd --zone=public --add-port=6379/tcp --permanent
    #重新加载配置
    firewall-cmd --reload
    #查看是否有nginx的线程是否存在
    ps -ef | grep nginx
    netstat -an -t -u | grep 6379

部署资料中的SpringBoot项目,部署前先把数据库安装好,然后再把项目的jar包上传到服务器中,然后运行jar包即可。

  1. 确认当前数据库状态

systemctl status mariadb

Linux_第5张图片

启动数据库

systemctl start mariadb

启动后再次通过systemctl status mariadb命令查看,确保数据库已经启动

Linux_第6张图片

  1. 确保数据库已启动后,通过Idea连接此数据库。

注意,此处的连接地址,是虚拟机中CentOS的IP地址

Linux_第7张图片

  1. 执行资料中提供的sql文件,创建此项目需要的schema

Linux_第8张图片

执行后查看连接中的schema,确保执行成功

Linux_第9张图片

  1. 修改项目中配置文件的数据库和连接地址,修改为虚拟机中数据库的地址

Linux_第10张图片

  1. 修改后运行项目,确保访问页面可以正常访问数据,访问地址:http://localhost:8080/pages/books.html

Linux_第11张图片

  1. 执行打包命令,生成jar包

Linux_第12张图片

  1. 把jar包上传到虚拟机中

  1. 进入jar包所在路径,执行java -jar命令

此处java -jar 是前台启动,如果退出窗口的话会关闭java程序

如果需要后台启动需要执行后台启动命令

后台启动命令

nohup java -jar boot_books-1.0-SNAPSHOT.jar &

后台启动并输出日志命令

nohup java -jar boot_books-1.0-SNAPSHOT.jar &> books.log &

  1. 输入访问地址,测试程序是否部署成功,访问地址为虚拟机IP地址+端口号+地址

Linux_第13张图片

四、Nginx反向代理

正向代理

正向代理类似一个中转站,代理内部访问外部资源。

举个例子:

  我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,它能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从那个网站的角度来看,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

注意:客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的IP地址,还有代理程序的端口。

总结来说:正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。

正向代理的用途:

   1. 访问原来无法访问的资源,如google
   2. 可以做缓存,加速访问资源
   3. 对客户端访问授权,上网进行认证
   4. 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理的作用

  1. 保证内网的安全,可以使用反向代理提供防火墙(WAF)功能,阻止web攻击。大型网站,通常将反向代理作为公网访问地址,Web服务器是内网。

  2. 负载均衡,通过反向代理服务器来优化网站的负载。当大量客户端请求代理服务器时,反向代理可以集中分发不同用户请求给不同的weab服务器进行处理请求。(本阶段不实现,负载均衡技术项目阶段讲解)

反向代理配置

  1. 修改配置文件

vim /usr/local/nginx/conf/nginx.conf

以下是被修订过的nginx.conf,将所有访问到nginx80端口的路径是/开头的请求,都转发到webcase代表的反向代理机群,默认是请求其中一台。

http{
    upstream bookssm{
        server 127.0.0.1:8080;
        #server 192.168.200.129:8080;
    }
    server {
        listen       80;
        server_name  localhost;
        location / {
             root html;
             #proxy_pass http://192.168.200.138:8080
             proxy_pass http://bookssm;
             index index.html index.htm;
        }
	}  
}
  • http块 一个http处理模块,可进行http的相关参数配置,内可以包含多个server块;

  • upstream块 配置反向代理及负载均衡,可以写多个upstream块,是定义在server块前面。

    • server localhost:8080; localhost可以指向网络任何一台主机。

  • server块 包含在http{}内部,每一个server{}都是一个虚拟主机(站点)监听

    • listen 监听端口

    • server_name 用于与http请求header头部的Host匹配

    • location 路径配置,符合某个路径执行块内规则

      • / 代表根下资源

        • root html 是根下的资源,可以从html目录获取。

        • index 默认页面(不输入网页时,默认访问页)

        • proxy_pass 反向代理,请求转发给 webcase所代表的主机群

  1. 重启服务器

/usr/local/nginx/sbin/nginx -s reload
  1. 测试访问

、Linux系统操作

1. 磁盘目录查看

  • pwd 显示当前在哪个目录

  • clear 清屏

  • ls:查看目录

    • 参数 -a 显示全部,包含隐藏

    • 参数 -l 列表形式显示

    ls -l 列表展示

    • “d”开头是目录,

    • “-” 开头是文件,

    • “l” 开头是链接文件

    ls -a 查看隐藏文件

    • . 开头的是隐藏文件或目录

    ls -la 列表展示,包含隐藏文件 简写命令是 ll -a 。

2.目录切换命令

  • cd usr 切换到该目录下usr目录

  • cd .. 切换到上一层目录

  • cd / 切换到系统根目录

  • cd ~ (波浪号 tilde) 切换到用户主目录

  • cd - 切换到上一个所在目录

    注意:

    • 绝对路径: 从根开始的,都称为绝对路径

      cd /etc: 进入根目录下的etc

    • 相对路径:从当前开始的,都称为相对路径

      cd etc: 进入当前目录下的etc :

      cd ./etc 同上

      cd ../root 进入当前上一级目录 ,.. 代表上一级目录

    输入目录时,使用tab,系统会智能提示

3. 磁盘文件创建

创建空文件:touch

  • touch:创建新文件命令 touch 文件名 默认创建的空文件。

添加内容到文件:echo

  • echo "内容" > a.txt 添加内容到文件,会覆盖

  • echo "内容" >> a.txt 追加内容到文件,追加到尾部

  • cat 文件 显示文件内容

  • cat a.txt >> b.txt a文件追加到b文件

备注:

echo $变量 显示变量的值

4. 磁盘文件及目录操作

linux操作系统命令格式: 命令 -[参数]

增加:mkdir

mkdir 目录名字 [目录名列表],效果如下:

  • mkdir a 在当前下创建a

  • mkdir test/a1 在 test下创建a1

  • mkdir b c d 在当前下同时创建 b、c、d目录

注意:不能跨级创建子目录

修改:mv

mv 文件或目录名 目标文件或目录名,效果如下:

  • 文件操作 mv a.txt b.txt : b.txt不存在即为重命名,存在会提示是否覆盖

  • 目录操作 mv test tmp :tmp不存在即为重命名,存在为移动效果

  • 文件对目录 mv a.txt ./tmp 移动文件到指定目录

复制:cp

cp [参数] 源文件或目录,目标文件或目录

参数: -r 递归

  • 单文件操作 cp a.txt a.txt.bak 在当前下复制一个文件

  • 多文件操作 cp ./web/* ./test 把web下的所有文件复制到test下

  • 递归操作 cp -r ./web/* ./test 把web下的所有文件及子目录复制到test下

删除:rm

rm [参数] 删除文件目录命令

参数: -r 递归 -f 忽略询问

  • rm a.txt 删除当前下的文件,会询问提示

  • rm -f a.txt 不询问直接删除

  • rm -rf ./test 递归删除test下的所有内容,包含test本身

  • rm -rf ./test/* 递归删除test下的所有内容,但是test不删除

    注意:删除一个目录,必须是rm -rf,否则不能删除

搜索:find

find 搜索位置 -name 字符串

  • find / - name 'java' 查java

  • find / -name '*redis' 查找含有redis的

5. 磁盘文件及目录权限

权限概述

权限是Linux中的重要概念,每个文件/目录等都具有权限,通过ls -l命令我们可以 查看某个目录下的文件或目录的权限

示例:在随意某个目录下ls -l

Linux_第14张图片

Linux_第15张图片

  • 文件的类型:

    • d:代表目录

    • -:代表文件

    • l:代表链接(可以认为是window中的快捷方式)

  • 后面的9位分为3组,每3位置一组,分别代表属主的权限,与当前用户同组的 用户的权限,其他用户的权限

    • r:代表权限是可读,r也可以用数字4表示

    • w:代表权限是可写,w也可以用数字2表示

    • x:代表权限是可执行,x也可以用数字1表示

Linux_第16张图片

权限设置

语法:chmod 数字或符号权限 [参数] 文件或目录

  • chmod u=rwx,g=rw,o=r aaa.txt

  • chmod 750 -R 文件或目录名 递归授权

  • chmod 755 文件或目录

  • chmod 777 -R 文件或目录

6. 文件内容浏览

  • cat命令 查看文件,只能显示文件最后一屏

    cat a.txt 查看文件全部内容

    注意:

    cat除了查看文件内容,还可以把文件内容进行合并

    cat a.txt >> b.txt 把a.txt文件输出到b.txt中

    比如:

    echo 'aaa' > a.txt

    echo 'bbb' > b.txt

    cat a.txt >> b.txt

  • more命令查询文件:分页查看所有内容,带百分比

    显示文件百分比,回车下一行,空格下一页,退出是Q

  • less命令查看文件:分页查看所有内容,带行号和百分比

    箭头上下代表上一行,下一行,空格显示下一页,退出是Q

    -N(大写) 显示行号

    -m 百分比

  • head/tail命令查看文件,支持显示的文件行数

    head 查看文件头部 内容

    tail 查看文件尾部内容

    -n 数字 代表行数

    -f 实时持续查看文件内容

7. 文件内容编辑(vi/vim)

  • vim:文件名

    适合快速修改纯文本文件,比如配置文件、属性文件、源文件等

  • vim编辑器有三种模式

    命令模式、编辑模式、底行模式,按ESC,退出当前模式,进入命令模式。

    • 命令模式

      刚刚进入是命令模式,从命令模式可进入编辑模式或底行模式。

      只接受命令关键字 其他字符不接受,通过输入相应的命令可以进入编辑模式

      dd:删除当前行

      yy:复制当前行

      p:粘贴

      整页翻页 ctrl-f、 f是forword , ctrl-b b就是backward

      shift+$是移动到行尾,0是移动到行首

    • 编辑模式

      进入编辑模式命令:i,o,a或者insert

      对文件进行内容编辑 任何字符都接受,内容编辑完毕之后 需要退回命令模式

      退回到命令模式,按ESC键

    • 底行模式

      在命令模式下,输入冒号 : ,进入底行模式。

      底行命令:

      • :wq,写入并退出,

      • :q! ,退出不保存

      • :set nu,显示行号

      • :set nu!,取消行号显示

      • :数字,定位行号

      • :/ 搜索字符,n是下一个,N是上一个

      • :noh 清除搜索高亮显示

  • vim编辑器使用过程关于vim使用过程:

    vim 文件-------->命令模式--------->输入i---------->编辑模式----------->编辑文件----------->按下Esc--------->命令模式--------->按下:---------->底行模式----------->输入wq保存并退出/q!强制退出不保存

8. 压缩文件管理

Linux中的打包文件一般是以.tar结尾的,压缩的命令一般是以.gz结尾的。而一般情况下打包和压缩是一起进行的,打包并压缩后的文件的后缀名一般.tar.gz。

tar命令:压缩和解压缩

  • 参数:-z 调用gzip压缩命令压缩

  • 参数:-c 打包文件

  • 参数:-C 在指定的目录解压缩

  • 参数:-v 显示命令的执行过程

  • 参数:-f 指定文件名

  • 参数:-x 解压缩

  • 示例:将test目录打成压缩包,压缩后文件名为 test.tar.gz

    • tar -zcvf test.tar.gz test

  • 示例:将test.tar.gz进行解压缩

    • tar -xvf test.tar.gz

    • tar -xvf test.tar.gz -C /usr/local 解压缩到指定的目录

zip命令 压缩命令

zip -r mydata.zip mydata #压缩mydata目录

zip -r abc123.zip abc 123.txt #把abc文件夹和123.txt压缩成为abc123.zip

unzip 解压缩命令

unzip -d /a/b filename.zip 将文件解压缩到/a/b目录里面

9.Linux系统命令

进程命令

ps命令:查看进程

  • 参数:-e 显示所有程序

  • 参数:-f 显示UID,PPIP

    ps -ef 显示所有进程

    UID :程序被该 UID(用户ID) 所拥有

    PID :就是这个程序的 ID

    PPID :则是其上级父程序的ID**

    C :CPU使用的资源百分比**

    STIME :系统启动时间**

    TTY :登入者的终端机位置**

    TIME :使用掉的CPU时间。**

    CMD :所下达的是什么指令**

kill命令:结束进程

参数:-9 强制杀死该进程

过滤命令

grep [option] 字符串或正则表达式 文件名

从指定文件,搜索匹配的字符串

-i 忽略大小写

  • 示例:

    grep -i test /etc/sudo.conf 中包含字符串“test”的内容,且忽略大小写

    grep '^d' /etc/sudo.conf 查找以d开头的数据

    A命令 |B命令 | C命令

将前一个命令的输出作为下一个命令的输入

可以任意组合,只要是上一级有内容输出,下一个管道就可以处理

  • ll | grep '^d' | grep '.d$'| grep '4月'

  • find / -name '*.log' | grep 'tomcat'

网络命令

查看IP

ifconfig 查看本机网络卡信息

测试网络

ping 查看与某台主机的连接情况

查看端口

netstat 查看本机被使用的端口号

参数:-a 显示所有连接

参数:-n 以网络IP地址代替名称

-t 显示tcp, -u 显示udp连接情况

常用

netstat -an -t -u | grep '8080'

lsof -i tcp:3306

重启关机命令

重启 reboot

关机 halt | shutdown

附录

安装iptables服务 【yum安装】

iptables是linux 系统自带的优秀且完全免费的基于包过滤的防火墙工具、它的功能十分强大、使用非常灵活、可以对流入、流出及流经服务器的数据包进行精细的控制。特别是它可以在一台非常低配置下跑的非常好。 centos系统,默认仅仅开放了22端口,其他端口需要使用iptables进行管理(开放、删除、保存规则等)

  • 安装iptables

yum install iptables-services
  • Linux_第17张图片

  • 添加规则 (比如开放8080端口)

    /sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT  
  • Linux_第18张图片

  • 保存规则

service iptables save
  • 配置开机启动

    把启动防火墙服务的命令,加入到开机启动的配置文件中即可。

    vim  /etc/profile
  • Linux_第19张图片

  • 查看与删除iptables中放行的规则

    #查看iptables列表,显示列表编号
    iptables -L -n --line-number
    Chain INPUT (policy ACCEPT)
    num  target     prot opt source               destination         
    1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 
    2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:3306 
    3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 
    4    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    #删除iptables列表中 编号为1的规则
    iptables -D INPUT 1
    

安装Mysql【yum安装】

  • yum命令安装

     yum -y install mysql-community-server

    如果出现如图所示,请参考【手动获取rpm文件】:

    • Linux_第20张图片

    • Linux_第21张图片

    需要下载205M的资源,需要根据网络情况,等待比较久的时间。

    安装完毕如下:

    • Linux_第22张图片

  • 手动获取rpm文件安装

    在线获取rpm包

    wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm

    安装下载的rpm文件

    rpm -ivh mysql-community-release-el7-5.noarch.rpm

    安装mysql-server

    yum install mysql-server 
  • 启动mysql服务

  service mysqld start
  • 查看初始密码【5.7版本执行如下命令,5.6版本,默认密码是空】

  grep "password" /var/log/mysqld.log

  • 登录mysql

  mysql -u root -p

输入初始密码,可以复制密码,并粘贴到输入密码的位置

  • 设置root密码

    1. 修改安全策略 (mysql5.7不允许设置比较简单的密码策略)

set global validate_password_policy=0;
set global validate_password_length=1;
  • Linux_第23张图片

2. 设置密码: set password = password('123456');

3. 授权远程连接

默认情况下mysql为安全起见,不支持远程登录mysql,所以需要设置开启远程登录mysql的权限

grant all privileges on *.* to 'root' @'%' identified by '123456';
flush privileges;
SET PASSWORD FOR 'root'@'%'= PASSWORD('123456');
  • Linux_第24张图片

  • 开放3306端口

    /sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
    service iptables save

安装与配置JDK [解压缩安装]

  • tar -xvf 解开压缩包到指定目录

    • tar -xvf jdk-8u211-linux-x64.tar.gz -C /usr/local

  • 编辑配置文件,并配置环境变量

    全局配置或当前用户配置,二选一即可。

    全局配置文件: vim /etc/profile 或 用户配置文件 vim ~/.bash_profile 推荐前者。

    vim  /etc/profile

    将以下代码复制到profile文件中的末尾。

    #set java environment
    JAVA_HOME=/usr/local/jdk1.8.0_211/
    CLASSPATH=.:$JAVA_HOME/lib.tools.jar
    PATH=$JAVA_HOME/bin:$PATH
    export JAVA_HOME CLASSPATH PATH 

    保存并退出

  • 加载环境变量

    source /etc/profile 或 source .bash_profile ,推荐前者。

    source  /etc/profile

    不出现任何提示,说明环境加载成功。

  • 测试环境

    输入 java或javac ,出现如下提示即为环境配置成功

    • Linux_第25张图片

    如果出现:

    • 前面的路径没有设置正确,请重新检查profile文件设置的路径与磁盘路径是否一致

    • 重新执行 source /etc/profile

Git部署Web项目

1. 拉取代码

  1. 在Git仓库平台增加服务端的ssh公钥

    在服务端机器生成密钥对,使用ssh命令,生成的密钥默认放在用户目录的.ssh目录。

    #生成密钥,输入完成命令,默认回车即可。
    ssh-keygen -t rsa -C "[email protected]"
    # 查看用户目录下的隐藏目录
    ls -a ~/ 
    # 查看.ssh目录下的密钥
    ls ~/.ssh/ 
    # 查看公钥信息
    cat .ssh/id_rsa.pub 

    -C "[email protected]" 如果省略默认是当前主机名称

    Linux_第26张图片

    复制生成后的 ssh key,通过仓库主页 「管理」->「部署公钥管理」->「添加部署公钥」 ,添加生成的 public key 添加到仓库中。

    Linux_第27张图片

  2. 使用SSH方式,克隆Git仓库代码

    cd ~       #切换到用户目录
    git clone [email protected]:mobapp/webcase.git
    cd ~/webcase
    #git clone [email protected]:mobapp/study_springmvc_ssm.git  #SSH方式克隆代码
    #cd study_springmvc_ssm # 进入项目根目录
    git branch # 查看当前分支,默认是master分支
    git pull # 拉取最新代码 [第1次不用]
    git checkout master # 切换到主分支 [第1次不用]

2. 项目打包

使用mvn命令,自动打包当前项目,默认生成在工程目录的target下

cd ~/webcase
mvn clean package -Dmaven.test.skip=true

备注:第1次打包,会非常慢,因为需要下载依赖库,可以把本地已经下载好的仓库直接放在用户目录的.m2下。

1.上传本地maven仓库到服务器m2目录下

Linux_第28张图片

2.解压缩本地仓库

cd ~/.m2
unzip -o repository

Linux_第29张图片

备注:-o 覆盖解压缩

3.重新打包

cd ~/webcase
mvn clean package -Dmaven.test.skip=true

3. 项目部署

把War把部署到Tomcat

把生成的war包移动或复制到tomcat webapps目录下即可,注意文件名就是应用的名称。

# 把war包copy到webapp是目录下,并取名为springssm.war 
# \cp 是强制覆盖,一般第2次部署时,是不需要确认的,直接覆盖
# cp 如果遇到重名,会提示覆盖
#\cp ~/study_springmvc_ssm/target/springmvc_ssm.war /usr/local/apache-tomcat-8.5.47/webapps/springssm.war
\cp ./target/webcase.war /usr/local/apache-tomcat-8.5.47/webapps/
#启动Tomcat 默认不用重启是可以的
/usr/local/apache-tomcat-8.5.47/bin/startup.sh
# 查看访问日志
tail -f /usr/local/apache-tomcat-8.5.47/logs/localhost_access_log.2022-04-24.txt
  1. 访问测试

    http://192.168.200.138:8080/webcase/login.html

Git部署Boot项目

1. 拉取代码

cd ~       #切换到用户目录
git clone [email protected]:mobapp/spring-boot-mybatis.git  #SSH方式克隆代码
cd spring-boot-mybatis # 进入项目根目录
git branch # 查看当前分支,默认是master分支
git pull # 拉取最新代码 [第1次不用]
git checkout master # 切换到主分支 [第1次不用]

2. 项目打包

mvn clean package -Dmaven.test.skip=true

3. 项目启动

  1. 启动mysql数据库【前面已启动】

  2. 安装项目数据库【前面已安装,本项目与之前项目用的同一数据库】

  3. 初始化项目的工作目录

    # 在当前创建工作目录
    mkdir ~/springmvcboot
    # 进入工作目录
    cd ~/springmvcboot
  4. 启动项目

# 强制负责编译之后的jar包到工作目录
\cp ~/spring-boot-mybatis/target/springboot_ssm.jar ~/springmvcboot
# 后台启动boot项目
nohup java -jar springboot_ssm.jar --server.port=8088 --spring.profiles.active=pro >springboot_ssm_out.log 2>&1 &
# 查看启动日志
tail -f springboot_ssm_out.log
# 开放端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
#重新加载配置
firewall-cmd --reload
  • nohup:不挂断地运行命令,退出帐户之后继续运行相应的进程。

  • springboot_ssm_out.log:是nohup把command的输出重定向到当前目录的指定的文件中.

    即输出内容不打印到屏幕上,而是输出到”日志文件名.log”文件中。

  • 2>&1 2就是标准错误,1是标准输出

    该命令相当于把标准错误重定向到标准输出么。这里&相当于标准错误等效于标准输出,即把标准错误和标准输出同时输出到指定的“日志文件名.log”文件中。

  1. 访问测试

http://192.168.200.138:8088/user/queryAll

注意boot项目,默认是发布在web的根目录下的。SSM项目只要发布到webapps/ROOT下才发布到根目录

部署SpringMVC项目

部署之前的综合案例,部署前先把数据库安装好,然后再把项目的war包copy到tomcat安装目录即可。

1. 初始化项目数据库

  1. msyql客户端工具连接VM中的mysql

  2. 在客户端工具中初始化数据库脚本

CREATE SCHEMA `ssm_db` DEFAULT CHARACTER SET utf8mb4;

use `ssm_db`;

-- ----------------------------
-- Table structure for tbl_book
-- ----------------------------
DROP TABLE IF EXISTS `tbl_book`;
CREATE TABLE `tbl_book`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tbl_book
-- ----------------------------
INSERT INTO `tbl_book` VALUES (1, '计算机理论', 'Spring实战 第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕');
INSERT INTO `tbl_book` VALUES (2, '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想');
INSERT INTO `tbl_book` VALUES (3, '计算机理论', 'Spring 5 设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式');
INSERT INTO `tbl_book` VALUES (4, '计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手');
INSERT INTO `tbl_book` VALUES (5, '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者');
INSERT INTO `tbl_book` VALUES (6, '计算机理论', 'Java核心技术 卷I 基础知识(原书第11版)', 'Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新');
INSERT INTO `tbl_book` VALUES (7, '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,大厂面试知识点全覆盖');
INSERT INTO `tbl_book` VALUES (8, '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉');
INSERT INTO `tbl_book` VALUES (9, '计算机理论', '零基础学Java(全彩版)', '零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术');
INSERT INTO `tbl_book` VALUES (10, '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
INSERT INTO `tbl_book` VALUES (11, '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍');
INSERT INTO `tbl_book` VALUES (12, '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');

以下是使用IDEA,初始化数据库:

Linux_第30张图片

Linux_第31张图片

2. 部署项目war包

  1. 使用IDEA打war包并上传到服务器

    1. 打包

    Linux_第32张图片

    1. 上传到服务器(注意:IP写自己的服务器)

  2. 停止当前的tomat服务器

    /usr/local/apache-tomcat-8.5.47/bin/shutdown.sh
  3. 上传war包到tomcat目录的webapps目录下

    (注意:IP写自己的服务器)

    scp book_ssm.war [email protected]:/app/apache-tomcat-8.5.47/webapps

    备注:SCP会自动覆盖之前上传的文件,Tomcat自动解压缩覆盖之前的文件

  4. 启动Tomcat服务器

    /usr/local/apache-tomcat-8.5.47/bin/startup.sh
  5. 浏览器测试

    http://192.168.188.128:8080/book_ssm/pages/books-tomcat.html

如果显示不正常,请查看日志:

tail -f  /usr/local/apache-tomcat-8.5.47/logs/catalina.out

瑞吉外卖项目优化-day08

课程内容

  • 前后端分离开发

  • Yapi

  • Swagger

  • 项目部署

前言

当前项目中,前端代码和后端代码混合在一起,是存在问题的,存在什么问题呢?

Linux_第33张图片

主要存在以下几点问题:

1). 开发人员同时负责前端和后端代码开发,分工不明确

2). 开发效率低

3). 前后端代码混合在一个工程中,不便于管理

4). 对开发人员要求高(既会前端,又会后端),人员招聘困难

为了解决上述提到的问题,现在比较主流的开发方式,就是前后端分离开发,前端人员开发前端的代码,后端开发人员开发服务端的业务功能,分工明确,各司其职。我们本章节,就是需要将之前的项目进行优化改造,变成前后端分离开发的项目。

1. 前后端分离开发

1.1 介绍

前后端分离开发,就是在项目开发过程中,对于前端代码的开发由专门的前端开发人员负责,后端代码则由后端开发人员负责,这样可以做到分工明确、各司其职,提高开发效率,前后端代码并行开发,可以加快项目开发进度。

目前,前后端分离开发方式已经被越来越多的公司所采用,成为当前项目开发的主流开发方式。

前后端分离开发后,从工程结构上也会发生变化,即前后端代码不再混合在同一个maven工程中,而是分为 前端工程后端工程

Linux_第34张图片

前后端分离之后,不仅工程结构变化,后期项目上线部署时,与之前也不同:

1). 之前: 前后端代码都混合在一起,我们只需要将前端和后端的代码统一打成jar包,直接运行就可以了。

2). 现在: 拆分为前后端分离的项目后,最终部署时,后端工程会打成一个jar包,运行在Tomcat中(springboot内嵌的tomcat)。前端工程的静态资源,会直接部署在Nginx中进行访问。

1.2 开发流程

前后端分离开发后,面临一个问题,就是前端开发人员和后端开发人员如何进行配合来共同开发一个项目?可以按照如下流程进行:

Linux_第35张图片

1). 定制接口: 这里所说的接口不是我们之前在service, mapper层定义的interface; 这里的接口(API接口)就是一个http的请求地址,主要就是去定义:请求路径、请求方式、请求参数、响应数据等内容。(具体接口文档描述的信息, 如上图)

2). 前后端并行开发: 依据定义好的接口信息,前端人员开发前端的代码,服务端人员开发服务端的接口; 在开发中前后端都需要进行测试,后端需要通过对应的工具来进行接口的测试,前端需要根据接口定义的参数进行Mock数据模拟测试。

3). 联调: 当前后端都开发完毕并且自测通过之后,就可以进行前后端的联调测试了,在这一阶段主要就是校验接口的参数格式。

4). 提测: 前后端联调测试通过之后,就可以将项目部署到测试服务器,进行自动化测试了。

1.3 前端技术栈

1). 开发工具

Visual Studio Code (简称VsCode)

Hbuilder

2). 技术框架

A. Node.js: Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。(类似于java语言中的JDK)。

B. Vue : 目前最火的的一个前端javaScript框架。

C. ElementUI: 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库,通过ElementUI组件可以快速构建项目页面。

D. Mock: 生成随机数据,拦截 Ajax 请求,前端可以借助于Mock生成测试数据进行功能测试。

E. Webpack: webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler),分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

2. Yapi

2.1 介绍

YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。

YApi让接口开发更简单高效,让接口的管理更具可读性、可维护性,让团队协作更合理。

源码地址: https://github.com/YMFE/yapi

官方文档: YApi 接口管理平台

要使用YApi,项目组需要自己进行部署,在本项目中我们可以使用课程提供的平台进行测试。L

域名: https://mock-java.itheima.net/

2.2 使用

2.2.1 准备

注册账号,登录平台

2.2.2 定义接口

登录到Yapi平台之后,我们可以创建项目,在项目下创建接口分类,在对应的分类中添加接口。

1). 创建项目

Linux_第36张图片

Linux_第37张图片

2). 添加分类

在当前项目中,有针对于员工、菜品、套餐、订单的操作,我们在进行接口维护时,可以针对接口进行分类,如果没有对应的分类,我们自己添加分类。

Linux_第38张图片

3). 添加接口

Linux_第39张图片

接口基本信息录入之后,添加提交,就可以看到该接口的基本信息:

Linux_第40张图片

但是目前,接口中我们并未指定请求参数,响应数据等信息,我们可以进一步点击编辑,对该接口 详情进行编辑处理。

Linux_第41张图片

Linux_第42张图片

Linux_第43张图片

4). 运行接口

Yapi也提供了接口测试功能,当我们接口编辑完毕后,后端服务的代码开发完毕,启动服务,就可以使用Yapi进行接口测试了。

Linux_第44张图片

注意: 由于菜品分页查询接口,是需要登录后才可以访问的,所以在测试该接口时,需要先请求员工管理接口中的登录接口,登录完成后,再访问该接口。

插件安装(运行时,如果是谷歌浏览器需要安排调试插件):

Linux_第45张图片

插件安装,可参考:chrome 安装 yapi 扩展教程 - 掘金,使用的插件已在资料中。

在Yapi平台中,将接口文档定义好了之后,前后端开发人员就需要根据接口文档中关于接口的描述进行前端和后端功能的开发。

2.2.3 导出接口文档

在Yapi平台中我们不仅可以在线阅读文档,还可以将Yapi中维护的文档直接导出来,可以导出md,json,html格式,在导出时自行选择即可 。

Linux_第46张图片

而在导出的html文件或md文件中,主要描述的就是接口的基本信息, 包括: 请求路径、请求方式、接口描述、请求参数、返回数据等信息。展示形式如下:

Linux_第47张图片

2.2.4 导入接口文档

上述我们讲解了接口文档的导出,我们也可以将外部的接口文档导入到Yapi的平台中,这样我们就不用一个接口一个接口的添加了。我们可以将课程资料中提供的json格式的接口文档直接导入Yapi平台中来。

Linux_第48张图片

导入过程中出现的确认弹窗,选择"确认"。

Linux_第49张图片

导入成功之后,我们就可以在Yapi平台查看到已导入的接口。

Linux_第50张图片

3. Swagger

3.1 介绍

官网:API Documentation & Design Tools for Teams | Swagger

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。功能主要包含以下几点:

A. 使得前后端分离开发更加方便,有利于团队协作

B. 接口文档在线自动生成,降低后端开发人员编写接口文档的负担

C. 接口功能测试

使用Swagger只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。

直接使用Swagger, 需要按照Swagger的规范定义接口, 实际上就是编写Json文件,编写起来比较繁琐、并不方便, 。而在项目中使用,我们一般会选择一些现成的框架来简化文档的编写,而这些框架是基于Swagger的,如knife4j。knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。而我们要使用kinfe4j,需要在pom.xml中引入如下依赖即可:


    com.github.xiaoymin
    knife4j-spring-boot-starter
    3.0.2

3.2 使用方式

接下来,我们就将我们的项目集成Knife4j,来自动生成接口文档。这里我们还是需要再创建一个新的分支v1.2,在该分支中进行knife4j的集成,集成测试完毕之后,没有问题,我们再将v1.2分支合并到master。

使用knife4j,主要需要操作以下几步:

1). 导入knife4j的maven坐标


    com.github.xiaoymin
    knife4j-spring-boot-starter
    3.0.2

2). 导入knife4j相关配置类并设置静态资源访问

这里我们就不需要再创建一个新的配置类了,我们直接在WebMvcConfig配置类中声明即可。

A. 在该配置类中加上两个注解 @EnableSwagger2 @EnableKnife4j ,开启Swagger和Knife4j的功能。

B. 在配置类中声明一个Docket类型的bean, 通过该bean来指定生成文档的信息。

C. 由于Swagger生成的在线文档中,涉及到很多静态资源,这些静态资源需要添加静态资源映射,否则接口文档页面无法访问。因此需要在 WebMvcConfig类中的addResourceHandlers方法中增加如下配置。

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
    
    @Autowired
	private ObjectMapper objectMapper;

    /**
     * 设置静态资源映射
     * 由于Swagger生成的在线文档中,涉及到很多静态资源,这些静态资源需要添加静态资源映射,否则接口文档页面无法访问。因此需要在 WebMvcConfig类中的addResourceHandlers方法中增加如下配置。
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始进行静态资源映射...");
        
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

    /**
     * 扩展mvc框架的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List> converters) {
        log.info("扩展消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        //messageConverter.setObjectMapper(new JacksonObjectMapper());
        messageConverter.setObjectMapper(objectMapper);
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0,messageConverter);
    }

    @Bean
    public Docket createRestApi() {
        // 文档类型
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.itheima.reggie.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    // // springfox.documentation.service.ApiInfo
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("瑞吉外卖")
                .version("1.0")
                .description("瑞吉外卖接口文档")
                .build();
    }
}

注意: Docket声明时,指定的有一个包扫描的路径,该路径指定的是Controller所在包的路径。因为Swagger在生成接口文档时,就是根据这里指定的包路径,自动的扫描该包下的@Controller, @RestController, @RequestMapping等SpringMVC的注解,依据这些注解来生成对应的接口文档。

3). 在LoginCheckFilter中设置不需要处理的请求路径

需要将Swagger及Knife4j相关的静态资源直接放行,无需登录即可访问,否则我们就需要登录之后,才可以访问接口文档的页面。

在原有的不需要处理的请求路径中,再增加如下链接:

"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"

Linux_第51张图片

3.3 查看接口文档

经过上面的集成配置之后,我们的项目集成Swagger及Knife4j就已经完成了,接下来我们可以重新启动项目,访问接口文档,访问链接为: http://localhost:8080/doc.html

Linux_第52张图片

我们可以看到,在所有的Controller中提供的所有的业务增删改查的接口,全部都已经自动生成了,我们通过接口文档可以看到请求的url、请求方式、请求参数、请求实例、响应的参数,响应的示例。 并且呢,我们也可以通过这份在线的接口文档,对接口进行测试。

Linux_第53张图片

注意: 由于我们服务端的Controller中的业务增删改查的方法,都是必须登录之后才可以访问的,所以,我们在测试时候,也是需要先访问登录接口。登录完成之后,我们可以再访问其他接口进行测试。

我们不仅可以在浏览器浏览生成的接口文档,Knife4j还支持离线文档,对接口文档进行下载,支持下载的格式有:markdown、html、word、openApi。

Linux_第54张图片

3.4 常用注解

3.4.1 问题说明

在上面我们直接访问Knife4j的接口文档页面,可以查看到所有的接口文档信息,但是我们发现,这些接口文档分类及接口描述都是Controller的类名(驼峰命名转换而来)及方法名,而且在接口文档中,所有的请求参数,响应数据,都没有中文的描述,并不知道里面参数的含义,接口文档的可读性很差。

Linux_第55张图片

3.4.2 注解介绍

为了解决上述的问题,Swagger提供了很多的注解,通过这些注解,我们可以更好更清晰的描述我们的接口,包含接口的请求参数、响应数据、数据模型等。核心的注解,主要包含以下几个:

注解 位置 说明
@Api 加载Controller类上,表示对类的说明
@ApiModel 类(通常是实体类) 描述实体类的作用
@ApiModelProperty 属性 描述实体类的属性
@ApiOperation 方法 说明方法的用途、作用
@ApiImplicitParams 方法 表示一组参数说明
@ApiImplicitParam 方法 用在@ApiImplicitParams注解中,指定一个请求参数的各个方面的属性

3.4.3 注解测试

1). 实体类

可以通过 @ApiModel , @ApiModelProperty 来描述实体类及属性

@Data
@ApiModel("套餐")
public class Setmeal implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键")
    private Long id;
    
    //分类id
    @ApiModelProperty("分类id")
    private Long categoryId;
    
    //套餐名称
    @ApiModelProperty("套餐名称")
    private String name;
​
    //套餐价格
    @ApiModelProperty("套餐价格")
    private BigDecimal price;
​
    //状态 0:停用 1:启用
    @ApiModelProperty("状态")
    private Integer status;
​
    //编码
    @ApiModelProperty("套餐编号")
    private String code;
​
    //描述信息
    @ApiModelProperty("描述信息")
    private String description;
​
    //图片
    @ApiModelProperty("图片")
    private String image;
​
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
​
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
​
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
​
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
}

2). 响应实体R

@Data
@ApiModel("返回结果")
public class R<T> implements Serializable{
​
    @ApiModelProperty("编码")
    private Integer code; //编码:1成功,0和其它数字为失败
​
    @ApiModelProperty("错误信息")
    private String msg; //错误信息
​
    @ApiModelProperty("数据")
    private T data; //数据
​
    @ApiModelProperty("动态数据")
    private Map map = new HashMap(); //动态数据
    
    //省略静态方法 ....
}    

3). Controller类及其中的方法

描述Controller、方法及其方法参数,可以通过注解: @Api, @APIOperation, @ApiImplicitParams, @ApiImplicitParam

@RestController
@RequestMapping("/setmeal")
@Slf4j
@Api(tags = "套餐相关接口")
public class SetmealController {
​
    @Autowired
    private SetmealService setmealService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SetmealDishService setmealDishService;
​
    /**
     * 新增套餐
     * @param setmealDto
     * @return
     */
    @PostMapping
    @CacheEvict(value = "setmealCache",allEntries = true)
    @ApiOperation(value = "新增套餐接口")
    public R<String> save(@RequestBody SetmealDto setmealDto){
        log.info("套餐信息:{}",setmealDto);
​
        setmealService.saveWithDish(setmealDto);
​
        return R.success("新增套餐成功");
    }
​
    /**
     * 套餐分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    @ApiOperation(value = "套餐分页查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "页码",required = true),
            @ApiImplicitParam(name = "pageSize",value = "每页记录数",required = true),
            @ApiImplicitParam(name = "name",value = "套餐名称",required = false)
    })
    public R<Page> page(int page,int pageSize,String name){
        //分页构造器对象
        Page<Setmeal> pageInfo = new Page<>(page,pageSize);
        Page<SetmealDto> dtoPage = new Page<>();
​
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据name进行like模糊查询
        queryWrapper.like(name != null,Setmeal::getName,name);
        //添加排序条件,根据更新时间降序排列
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
​
        setmealService.page(pageInfo,queryWrapper);
​
        //对象拷贝
        BeanUtils.copyProperties(pageInfo,dtoPage,"records");
        List<Setmeal> records = pageInfo.getRecords();
​
        List<SetmealDto> list = records.stream().map((item) -> {
            SetmealDto setmealDto = new SetmealDto();
            //对象拷贝
            BeanUtils.copyProperties(item,setmealDto);
            //分类id
            Long categoryId = item.getCategoryId();
            //根据分类id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category != null){
                //分类名称
                String categoryName = category.getName();
                setmealDto.setCategoryName(categoryName);
            }
            return setmealDto;
        }).collect(Collectors.toList());
​
        dtoPage.setRecords(list);
        return R.success(dtoPage);
    }
​
    /**
     * 删除套餐
     * @param ids
     * @return
     */
    @DeleteMapping
    @CacheEvict(value = "setmealCache",allEntries = true)
    @ApiOperation(value = "套餐删除接口")
    public R<String> delete(@RequestParam List<Long> ids){
        log.info("ids:{}",ids);
​
        setmealService.removeWithDish(ids);
​
        return R.success("套餐数据删除成功");
    }
​
    /**
     * 根据条件查询套餐数据
     * @param setmeal
     * @return
     */
    @GetMapping("/list")
    @Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")
    @ApiOperation(value = "套餐条件查询接口")
    public R<List<Setmeal>> list(Setmeal setmeal){
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
​
        List<Setmeal> list = setmealService.list(queryWrapper);
​
        return R.success(list);
    }
}
​

4). 重启服务测试

我们上述通过Swagger的注解,对实体类及实体类中的属性,以及Controller和Controller的方法进行描述,接下来,我们重新启动服务,然后看一下自动生成的接口文档有何变化。

Linux_第56张图片

在接口文档的页面中,我们可以看到接口的中文描述,清晰的看到每一个接口是做什么的,接口方法参数什么含义,参数是否是必填的,响应结果的参数是什么含义等,都可以清楚的描述出来。

总之,我们要想清晰的描述一个接口,就需要借助于Swagger给我们提供的注解。

4. 项目部署

在本章节,我们要做的是项目的部署,包含前端项目的部署,及后端项目的部署。

4.1 部署架构

Linux_第57张图片

PC端: 主要是为餐厅的员工及管理员使用的后台管理系统,对分类、菜品、套餐信息进行维护。

移动端: 可以基于微信公众号或小程序实现,我们课上并未实现,这部分的工作是前端开发人员需要开发的。

防火墙:硬件产品,让访问服务器更加安全

前端部署服务器: Nginx(反向代理)

后端部署服务器: 项目部署服务器

4.2 环境说明

具体的服务器的软件安装如下:

服务器 软件 名称
Nginx服务器 Nginx(部署前端项目、配置反向代理)
项目部署服务器 JDK1.8、Git、Maven
数据库服务器 MySQL数据库
Redis服务器 Redis(缓存中间件)

以上需要的软件安装,可以参考

4.3 前端项目部署

1). 在服务器A中安装Nginx,将课程资料中的静态资源目录上传到Nginx的html目录下

Linux_第58张图片

将整个目录上传至/usr/local/nginx/html目录下

上传完成后,如图所示

Linux_第59张图片

执行解压缩命令

unzip html.zip

2). 修改Nginx配置文件nginx.conf

将nginx.conf配置文件中,将原有的监听80, 82, 8080端口号 的虚拟主机注释掉,引入如下的配置信息:

  upstream boot{
        # 200.1 宿主机
        server 192.168.200.138:8080;
        #server 192.168.200.129:8080;
  }
  server {
        listen       80;
        server_name  localhost;        location / {
            root   html;
            index  index.html;
        }
        # http://192.168.188.128/api/employee/login
        # 会被这个配置拦截住
        location ^~ /api/ {
            # 重定向的操作    
            # /employee/login
            rewrite ^/api/(.*)$ /$1 break;
            # http://192.168.200.138:8080/employee/login
            proxy_pass http://boot;
        }
        
        location = /50x.html {
            root   html;
        }
    }

3). 通过nginx访问前端工程

http://192.168.200.138/backend/page/login/login.html

4.4 反向代理配置

前端工程部署完成之后,我们可以正常的访问到系统的登录页面,点击登录按钮,可以看到服务端发起的请求,请求信息如下:

Linux_第60张图片

而大家知道,在我们之前开发的工程中,是没有/api这个前缀的,那这个时候,在不修改服务端代码的情况下,如何处理该请求呢?

实际上,通过nginx的就可以轻松解决这个问题。

在上述我们配置的nginx.conf中,除了配置了静态资源的加载目录以外,我们还配置了一段反向代理的配置,配置信息如下:

upstream boot{
        # 200.1 宿主机
        server 192.168.200.138:8080;
        #server 192.168.200.129:8080;
}location ^~ /api/ {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://boot;
}

这一段配置代表,如果请求当前nginx,并且请求的路径如果是 /api/ 开头,将会被该location处理。而在该location中,主要配置了两块儿信息: rewrite(url重写) 和 proxy_pass(反向代理)。 接下来我们就来解析一下这两项的配置。

1). 路径重写rewrite

rewrite ^/api/(.*)$ /$1 break;

这里写的是一个正则表达式,代表如果请求路径是以 /api/ 开头,后面的请求路径任意,此时将原始的url路径重写为 /$1,这里的$1指代的就是通配符 .* 这一块的内容。比如:

/api/employee/login ------> ^/api/(.*)$ --------> 此时 (.*) 匹配的就是 employee/login ------> 最终重写为/$1 : /employee/login

2). 反向代理

proxy_pass http://boot;

boot是一个虚拟名称的代表,代表是就是前面定义的upstream boot 。boot 代表是一个机器的集群。可以根据负载策略随机选择一台。如果仅有一台直接转发到这台主机。

路径重写后的请求,将会转发到后端的 http://192.168.200.138:8080 服务器中。

4.5 项目服务端部署

SpringBoot项目部署的核心思路与步骤:

  1. 环境安装:部署环境的安装

  2. 拉取代码:通过git命令,克隆并拉取仓库的代码,默认是master分支(发布时都用此分支)

  3. 编译打包:通过maven命令,对项目代码进行编译打包,输出jar包

  4. 启动项目:把输出的jar包复制到工作目录(运维人员指定的目录),并在后台启动。

  5. 测试后端接口:使用postman测试接口是否正常访问。

  6. 脚本部署与发布:如果经常修改项目,需要重新打包上线,建议直接使用脚本

1.环境安装

A. 确认JDK环境

B. 确认Git环境

C. 确认Maven环境

2.拉取代码

# 进入用户目录
cd ~
# 克隆代码 ,克隆后默认检查的master分支
git clone git@gitee.com:mobapp/reggie_take_out.git 
# 进入项目目录
cd ~/reggie_take_out
# 拉取代码(第1次克隆后,已经拉取过了,可以不执行)
git pull

如果克隆时出现如下提示:

Linux_第61张图片

说明需要把把当前服务器的SSH公钥放在gitee服务器上,才可以通过SSH协议拉取仓库的代码。

3.编译项目

1.进入仓库目录根目录,执行编译命令

# 进入项目目录
cd ~/reggie_take_out
mvn clean package -Dmaven.test.skip=true

正常编译如下:

Linux_第62张图片

备注:在执行mvn打包时,需要下载项目用的依赖仓库,如果网速很慢,这个过程会花费很长时间,如图所示:

Linux_第63张图片

建议ctrl+c强行终止,然后把本地的maven仓库或提供的mvn仓库,上传到服务器mvn默认仓库。

2.解压缩mvn仓库(编译失败,才执行此步骤)

mvn默认仓库是在用户目录下,以.m2开头

  • 把git仓库放在.m2下

cd ~/soft
# 解压到当前目录
unzip git仓库.zip
# 把解压的文件复制到 .m2下
cp -rf ./git仓库/*.* ~/.m2/

Linux_第64张图片

  • 解压缩上传的仓库,覆盖默认仓库

cd ~/.m2
unzip -o repository.zip

Linux_第65张图片

  • 再次执行编译指令

    cd ~/reggie_take_out
    mvn clean package -Dmaven.test.skip=true

    Linux_第66张图片

4.启动项目

  1. 启动之前先启动nginx、mysql、redis

备注:mysql数据库,需要安装reggie项目;redis暂时可以远程连接。

  • 启动nginx: /usr/local/nginx/sbin/nginx

  • 启动mysql(之前安装的mariadb): systemctl start mariadb

  • 在服务器上安装瑞吉项目库

Linux_第67张图片

  • 远程连接redis

    Linux_第68张图片

  1. 创建工作目录,把jar复制到工作目录

cd ~/
mkdir reggie_project
# reggie_take_out目录与自己的项目对应
# reggie_take_out-1.0-SNAPSHOT.jar文件 与自己的项目对应
\cp ~/reggie_take_out/target/reggie_take_out-1.0-SNAPSHOT.jar ~/reggie_project/
​
  1. 后台启动jar包

cd ~/reggie_project/
#reggie_take_out-1.0-SNAPSHOT.jar 与自己的项目名称对应
nohup java -jar reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &
# 查看启动日志
tail -f reggie_take_out.log

5.测试后端接口

测试登录

Linux_第69张图片

测试发送验证码(主要是测试Redis)

Linux_第70张图片

nohup java -jar -Dspring.profiles.active=pro reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &

6.脚本部署与发布

1.把脚本上传到工作目录

将资料中提供的start-reggie.sh和stop-reggie.sh文件上传到服务器工作目录

Linux_第71张图片

备注:.sh文件的将多个命令合并在一起的批处理命令。

2.设置脚本执行权限

cd ~/reggie_project/
chmod 755 *.sh

3) 执行start-reggie.sh脚本文件,自动部署项目

Linux_第72张图片

执行完shell脚本之后,我们可以通过 ps -ef|grep java 指令,查看服务是否启动。

查看启动日志

 tail -f reggie_take_out.log

4). 访问系统测试

http://192.168.200.138/backend/page/login/login.html

4.6 图片展示问题处理

在上述的测试中,我们发现菜品的图片无法正常展示。原因是因为,在我们的配置文件中,图片信息依然是从 D:/img 中加载的,但是在Linux服务器中,是不存在D盘的。

1). 修改文件存储目录,并提交代码

将文件存储目录修改为:

reggie:
  path: /usr/local/img/

2). 执行shell脚本,进行自动化部署

3).访问测试

http://192.168.200.138/backend/index.html

瑞吉外卖项目优化-Day02

课程内容

  • MySQL主从复制

  • 读写分离案例

  • 项目实现读写分离

  • Nginx-概述

  • Nginx-命令

  • Nginx-应用

前言

1). 存在的问题

在前面基础功能实现的过程中,我们后台管理系统及移动端的用户,在进行数据访问时,都是直接操作数据库MySQL的。结构如下图:

Linux_第73张图片

而在当前,MySQL服务器只有一台,那么就可能会存在如下问题:

1). 读和写所有压力都由一台数据库承担,压力大

2). 数据库服务器磁盘损坏则数据丢失,单点故障

2). 解决方案

为了解决上述提到的两个问题,我们可以准备两台MySQL,一台主(Master)服务器,一台从(Slave)服务器,主库的数据变更,需要同步到从库中(主从复制)。而用户在访问我们项目时,如果是写操作(insert、update、delete),则直接操作主库;如果是读(select)操作,则直接操作从库(在这种读写分离的结构中,从库是可以有多个的),这种结构我们称为 读写分离 。

Linux_第74张图片

今天我们就需要实现上述的架构,来解决业务开发中所存在的问题。

1. MySQL(Mariadb)主从复制

MySQL数据库默认是支持主从复制的,不需要借助于其他的技术,我们只需要在数据库中简单的配置即可。接下来,我们就从以下的几个方面,来介绍一下主从复制:

1.1 介绍

MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现 从库 的数据和 主库 的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。

二进制日志:

二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用,MySQL的主从复制, 就是通过该binlog实现的。默认MySQL是未开启该日志的。

MySQL的主从复制原理如下:

Linux_第75张图片

MySQL复制过程分成三步:

1). MySQL master 将数据变更写入二进制日志( binary log)

2). slave将master的binary log拷贝到它的中继日志(relay log)

3). slave重做中继日志中的事件,将数据变更反映它自己的数据

1.2 搭建

1.2.1 准备工作

提前准备两台服务器,并且在服务器中安装MySQL,服务器的信息如下:

数据库 IP 数据库版本
Master 192.168.200.200 5.7.25
Slave 192.168.200.201 5.7.25

并在两台服务器上做如下准备工作:

注意:如果已放开相应的端口号,就不需要再执行此操作了

1). 防火墙开放3306端口号

# 放开3306端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent
# 重新加载配置
firewall-cmd --reload
# 显示当前放开的端口号
firewall-cmd --zone=public --list-ports

2). 并将两台数据库服务器启动起来:

注意:此处根据自己安装的数据库启动

如果数据库已启动,就不需要再执行此操作了

启动Mariadb

systemctl start mariadb

启动MySQL

systemctl start mysqld

登录MySQL,验证是否正常启动

Linux_第76张图片

1.2.2 主库配置

服务器: 192.168.200.200

1). 修改Mysql数据库的配置文件/etc/my.cnf

在最下面增加配置:

log-bin=mysql-bin   #[必须]启用二进制日志
server-id=200       #[必须]服务器唯一ID(唯一即可)

Linux_第77张图片

2). 重启Mysql(Mariadb)服务

执行指令:

此处根据自己安装的数据库启动

重启Mariadb

systemctl restart mariadb

重启MySql

 systemctl restart mysqld

3). 创建数据同步的用户并授权

登录mysql

mysql -u root -p

并执行如下指令,创建用户并授权:

GRANT REPLICATION SLAVE ON *.* to 'xiaoming'@'%' identified by 'Root@123456';

注:上面SQL的作用是创建一个用户 xiaoming ,密码为 Root@123456 ,并且给xiaoming用户授予REPLICATION SLAVE权限。常用于建立复制时所需要用到的用户权限,也就是slave必须被master授权具有该权限的用户,才能通过该用户复制。

MySQL密码复杂程度说明:

目前mysql5.7默认密码校验策略等级为 MEDIUM , 该等级要求密码组成为: 数字、小写字母、大写字母 、特殊字符、长度至少8位

4). 登录Mysql数据库,查看master同步状态

执行下面SQL,记录下结果中FilePosition的值

show master status;

注:上面SQL的作用是查看Master的状态,执行完此SQL后不要再执行任何操作

1.2.3 从库配置

服务器: 192.168.200.201

1). 修改Mysql数据库的配置文件/etc/my.cnf

server-id=201 	#[必须]服务器唯一ID

Linux_第78张图片

2). 重启Mysql(Mariadb)服务

执行指令:

注意:此处根据自己安装的数据库启动

重启Mariadb

systemctl restart mariadb

重启MySql

 systemctl restart mysqld

3). 登录Mysql数据库,设置主库地址及同步位置

change master to master_host='192.168.188.128',master_user='xiaoming',master_password='Root@123456',master_log_file='mysql-bin.000001',master_log_pos=396;

start slave;

参数说明:

A. master_host : 主库的IP地址

B. master_user : 访问主库进行主从复制的用户名(上面在主库创建的)

C. master_password : 访问主库进行主从复制的用户名对应的密码

D. master_log_file : 从哪个日志文件开始同步(上述查询master状态中展示的有)

E. master_log_pos : 从指定日志文件的哪个位置开始同步(上述查询master状态中展示的有)

4). 查看从数据库的状态

show slave status;

然后通过状态信息中的 Slave_IO_running 和 Slave_SQL_running 可以看出主从同步是否就绪,如果这两个参数全为Yes,表示主从同步已经配置完成。

MySQL命令行技巧:

\G : 在MySQL的sql语句后加上\G,表示将查询结果进行按列打印,可以使每个字段打印到单独的行。即将查到的结构旋转90度变成纵向;

1.3 测试

主从复制的环境,已经搭建好了,接下来,我们可以通过Navicat连接上两台MySQL服务器,进行测试。测试时,我们只需要在主库Master执行操作,查看从库Slave中是否将数据同步过去即可。

1). 在master中创建数据库itcast, 刷新slave查看是否可以同步过去

Linux_第79张图片

2). 在master的itcast数据下创建user表, 刷新slave查看是否可以同步过去

Linux_第80张图片

3). 在master的user表中插入一条数据, 刷新slave查看是否可以同步过去

Linux_第81张图片

2. 读写分离案例

2.1 背景介绍

面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

Linux_第82张图片

通过读写分离,就可以降低单台数据库的访问压力, 提高访问效率,也可以避免单机故障。

主从复制的结构,我们在第一节已经完成了,那么我们在项目中,如何通过java代码来完成读写分离呢,如何在执行select的时候查询从库,而在执行insert、update、delete的时候,操作主库呢?这个时候,我们就需要介绍一个新的技术 ShardingJDBC。

2.2 ShardingJDBC介绍

Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

使用Sharding-JDBC可以在程序中轻松的实现数据库读写分离。

Sharding-JDBC具有以下几个特点:

1). 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。

2). 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。

3). 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。

依赖:


    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0-RC1

2.3 数据库环境

在主库中创建一个数据库rw, 并且创建一张表, 该数据库及表结构创建完毕后会自动同步至从数据库,SQL语句如下:

create database rw default charset utf8mb4;

use rw;

CREATE TABLE `user` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO user (name, age, address) VALUES ('张三', 100, '昌平');
INSERT INTO user (name, age, address) VALUES ('李四', 0, '顺义');
INSERT INTO user (name, age, address) VALUES ('星越L', 21, '北京');

Linux_第83张图片

2.4 初始工程导入

我们本案例主要是演示一下读写分离操作,对于基本的增删改查的业务操作,我们就不再去编写了,我们可以直接导入资料中提供的demo工程(rw_demo),在demo工程中,我们已经完成了user的增删改查操作,具体的工程结构如下:

Linux_第84张图片

2.5 读写分离配置

1). 在pom.xml中增加shardingJdbc的maven坐标


    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0-RC1

2). 在application.yml中增加配置

spring:
  main:
    # 如果当前项目中存在同名的bean,后定义的bean会覆盖先定义的
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      names:
        master,slave
      # 主数据源
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.200:3306/rw?characterEncoding=utf-8
        username: root
        password: root
      # 从数据源
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.201:3306/rw?characterEncoding=utf-8
        username: root
        password: root
    masterslave:
      # 读写分离配置
      load-balance-algorithm-type: round_robin #轮询
      # 最终的数据源名称
      name: dataSource
      # 主库数据源名称
      master-data-source-name: master
      # 从库数据源名称列表,多个逗号分隔
      slave-data-source-names: slave
    props:
      sql:
        show: true #开启SQL显示,默认false

配置解析:

Linux_第85张图片

如果不配置该项,项目启动之后将会报错:

报错信息表明,在声明 org.apache.shardingsphere.shardingjdbc.spring.boot 包下的SpringBootConfiguration中的dataSource这个bean时出错, 原因是有一个同名的 dataSource 的bean在com.alibaba.druid.spring.boot.autoconfigure包下的DruidDataSourceAutoConfigure类加载时已经声明了。

Linux_第86张图片

Linux_第87张图片

而我们需要用到的是 shardingjdbc包下的dataSource,所以我们需要配置上述属性,让后加载的覆盖先加载的。

2.6 测试

我们使用shardingjdbc来实现读写分离,直接通过上述简单的配置就可以了。配置完毕之后,我们就可以重启服务,通过postman来访问controller的方法,来完成用户信息的增删改查,我们可以通过debug及日志的方式来查看每一次执行增删改查操作,使用的是哪个数据源,连接的是哪个数据库。

1). 保存数据

控制台输出日志,可以看到操作master主库:

2). 修改数据

Linux_第88张图片

控制台输出日志,可以看到操作master主库:

3). 查询数据

Linux_第89张图片

控制台输出日志,可以看到操作slave主库:

4). 删除数据

Linux_第90张图片

控制台输出日志,可以看到操作master主库:

3. 项目实现读写分离

3.1 数据库环境准备

直接使用我们前面在虚拟机中搭建的主从复制的数据库环境即可。在主库中创建瑞吉外卖项目的业务数据库reggie, 并导入相关表结构和数据(我们可以将自己之前在本地开发时使用的数据库数据导出, 然后导入到服务器中的主库即可)。

1). 将自己本地的reggie数据库的数据导出SQL文件

Linux_第91张图片

这样做的话,我们之前自己开发时,添加的测试数据都还在的,便于测试。

2). 在主数据库master中,创建数据库reggie,并导入该SQL文件

master中创建数据库,会自动同步至slave从库

Linux_第92张图片

在master的reggie中导入sql文件

Linux_第93张图片

3.2 创建Git分支

目前默认git中有两个分支master 和 v1.0 ,我们接下来进行读写分离的优化,就不在master和v1.0分支来操作了,我们需要在git上创建一个单独的分支v1.1,读写分离的优化,我们就在该分支上进行操作。具体创建分支的操作,和前面演示的一致。

当前创建的v1.1分支,是基于master分支创建出来的,所以目前master分支的代码, 和v1.1分支的代码是完全一样的,接下来把v1.1的代码也推送至远程仓库。

3.3 读写分离配置

1). 在项目的pom.xml增加依赖


    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0-RC1

2). 在项目的application.yml中配置数据源相关信息

spring:
  main:
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      names:
        master,slave
      # 主数据源
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.200:3306/reggie?characterEncoding=utf-8
        username: root
        password: root
      # 从数据源
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.201:3306/reggie?characterEncoding=utf-8
        username: root
        password: root
    masterslave:
      # 读写分离配置
      load-balance-algorithm-type: round_robin #轮询
      # 最终的数据源名称
      name: dataSource
      # 主库数据源名称
      master-data-source-name: master
      # 从库数据源名称列表,多个逗号分隔
      slave-data-source-names: slave
    props:
      sql:
        show: true #开启SQL显示,默认false

3.4 功能测试

配置完毕之后,我们启动项目进行测试,直接访问系统管理后台的页面,然后执行相关业务操作,看控制台输出的日志信息即可。

查询操作:

更新操作:

插入操作:

删除操作:

3.5 Git合并代码

读写分离的功能我们已经实现完毕了,那么接下来,我们就可以将当前分支v1.1代码提交并推送到远程仓库。

Linux_第94张图片

Linux_第95张图片

然后,再将v1.1的代码,合并到master分支,然后推送至远程仓库。

Linux_第96张图片

4. Nginx-概述

4.1 介绍

Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx的网站有:百度、京东、新浪、网易、腾讯、淘宝等。

Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。

官网:nginx news

4.2 下载和安装

4.2.1 下载

在Nginx的官网的下载页面中(nginx: download),就展示了当前Nginx版本,并提供了下载的连接。 如下:

Linux_第97张图片

在本项目中,我们所学习的Nginx选择的是稳定版本的1.16这个版本,我们可以直接从官网下载,当然在我们的课程资料中也已经提供了该版本的安装包。

4.2.2 安装

1). 安装依赖包

由于nginx是基于c语言开发的,所以需要安装c语言的编译环境,及正则表达式库等第三方依赖库。

yum -y install gcc pcre-devel zlib-devel openssl openssl-devel

2). 下载Nginx安装包

yum install wget
wget https://nginx.org/download/nginx-1.16.1.tar.gz

wget :

wget命令用来从指定的URL下载文件。wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。

执行完wget指令后,就会在当前所在目录看到下载下来的文件。

3). 解压nginx压缩包

tar -zxvf nginx-1.16.1.tar.gz

4). 配置Nginx编译环境

cd nginx-1.16.1
./configure --prefix=/usr/local/nginx

说明:

--prefix 指定的目录,就是我们安装Nginx的目录。

5). 编译&安装

make & make install

4.3 目录结构

安装完Nginx后,我们可以切换到Nginx的安装目录(/usr/local/nginx),先来熟悉一下Nginx的目录结构,如下图:

Linux_第98张图片

备注:

上述我们用到的一个指令 tree,该指令可以将我们指定的目录以树状结构展示出来。如果没有这个指令,可以通过以下指令进行安装。

yum install tree

重点目录和文件如下:

目录/文件 说明 备注
conf 配置文件的存放目录
conf/nginx.conf Nginx的核心配置文件 conf下有很多nginx的配置文件,我们主要操作这个核心配置文件
html 存放静态资源(html, css, ) 部署到Nginx的静态资源都可以放在html目录中
logs 存放nginx日志(访问日志、错误日志等)
sbin/nginx 二进制文件,用于启动、停止Nginx服务

5. Nginx-命令

5.1 常用命令

Nginx中,我们的二进制可执行文件(nginx)存放在sbin目录下,虽然只有一个可执行文件,但是我们可以通过该指令配合不同的参数达到更加强大的功能。接下来,我们就演示一下Nginx常见指令, 在执行下面的指令时,都需要在/usr/local/nginx/sbin/目录下执行。

1). 查看版本

./nginx -v

2). 检查配置文件

修改了nginx.conf核心配置文件之后,在启动Nginx服务之前,可以先检查一下conf/nginx.conf文件配置的是否有错误,命令如下:

./nginx -t

3). 启动

./nginx

启动之后,我们可以通过ps -ef指令来查看nginx的进程是否存在。

注意: nginx服务启动后,默认就会有两个进程。

启动之后,我们可以直接访问Nginx的80端口, http://192.168.200.200

Linux_第99张图片

注意:

要想正常访问Nginx,需要关闭防火墙或开放指定端口号,执行的指令如下:

A. 关闭防火墙

systemctl stop firewalld

B. 开放80端口

firewall-cmd --zone=public --add-port=80/tcp --permanent

firewall-cmd --reload

4). 停止

./nginx -s stop

停止之后,我们可以查看nginx的进程:

ps -ef|grep nginx

5). 重新加载

当修改了Nginx配置文件后,需要重新加载才能生效,可以使用下面命令重新加载配置文件:

./nginx -s reload

6. Nginx-应用

介绍了并安装了Nginx之后,本章节将要讲解的是Nginx的使用,我们主要从以下四个方面进行讲解。

6.1 配置文件结构

nginx的配置文件(conf/nginx.conf)整体上分为三部分: 全局块、events块、http块。这三块的分别配置什么样的信息呢,看下表:

区域 职责
全局块 配置和nginx运行相关的全局配置
events块 配置和网络连接相关的配置
http块 配置代理、缓存、日志记录、虚拟主机等配置

具体结构图如下:

Linux_第100张图片

在全局块、events块以及http块中,我们经常配置的是http块。

在http块中可以包含多个server块,每个server块可以配置多个location块。

6.2 部署静态资源

6.2.1 介绍

Nginx可以作为静态web服务器来部署静态资源。这里所说的静态资源是指在服务端真实存在,并且能够直接展示的一些文件,比如常见的html页面、css文件、js文件、图片、视频等资源。

相对于Tomcat,Nginx处理静态资源的能力更加高效,所以在生产环境下,一般都会将静态资源部署到Nginx中。

将静态资源部署到Nginx非常简单,只需要将文件复制到Nginx安装目录下的html目录中即可。

server {
    listen 80;              #监听端口   
    server_name localhost;  #服务器名称
    location / {            #匹配客户端请求url
        root html;          #指定静态资源根目录
        index index.html;   #指定默认首页
    }
}

Linux

Linux目录结构

Linux_第101张图片

Linux操作

命令 解释
磁盘命令
pwd 显示当前在哪个目录
clear 清屏
ls 查看目录(-a 显示全部、-l列表形式)
ls -al 展示所有("d"开头目录、"-"文件、"|"链接)
cd .. 切换到上一层
cd / 切换到系统根目录
cd ~ 切换到用户主目录
cd - 切换到上一个所在目录
cd etc 进入当前目录下得etc
cd ../root 进入当前上一级目录
文件操作
touch 创建文件命令
echo "内容" > a.txt 添加内容到文件,会覆盖
echo "内容" >> a.txt 添加内容到文件中,追加尾部
cat 文件 显示文件内容
cat a.txt >> b.txt a文件追加到b文件
echo $变量 显示变量的值
文件夹操作
mkdir 名称 创建名称的目录
mv a.txt b.txt 移动文件a.txt 并改名为b.txt
mv test tmp 移动test到tmp
cp a.txt b.txt 复制a到b内
cp -r ./web/* ./test 把web下所有文件及子目录复制到test下
rm a.txt 删除当前文件,会询问
rm -f a.txt 直接删除不会询问
rm -rf ./test/* 递归删除test下所有内容
find / -name 'java' 查询java
find / -name '*redis' 查找包含redis的
目录权限
chmod u=rwx,g=rw,o=r a.txt 修改文件权限
chmod 750 -R 文件递归授权
chmod 777 -R 文件目录递归授权
文件内容浏览
cat a.txt 查看a.txt文件全部内容
cat a.txt >> b.txt 把a.txt文件输出到b.txt中
more 文件名 分页查看文件内容
less 文件名 分页查看文件内容(-N 显示行号、-m百分比)退出是Q
head 文件 查看文件头部
tail -f 文件名 实时线持续查看文件内容
文件内容编辑
vim 文件名 进入查看文件
文件内命令
Esc切换模式 命令模式、编辑模式、底行模式
dd 删除改行
yy 复制当前行
p 粘贴
ctrl-f 整页翻页
i、o、a、insert 进入编辑模式
wq 底行模式下写入并退出
q! 退出不保存
wq! 强制保存并退出
set nu 显示行号
set nu! 取消显示行号
:数字 定位行号
/字符 搜索字符(n是下一个、shfit N上一个)
noh 清楚高亮
压缩命令
tar -zcvf test.tar.gz test 将test目录打成压缩包,压缩后文件没那个为test.tar.gz
tar -xvf test.tar.gz 将test.tar.gz进行解压
tar -xvf test.tar.gz -C /usr/local 解压缩到指定目录
zip -r mydata.zip mydata 压缩mydata目录
zip -r ab.zip a b.txt 把a文件夹和b.txt压缩成为ab.zip
unzip -d /a/b filename.zip 将文件解压到/a/b目录内
ps -ef 显示所有进程
kill -9 进程id(PID) 结束进程
grep [option] 匹配正则或者字符串
ifconfig 查看本机网络信息
ping 查看连接状态
netstat 查看本机使用的端口号

Linux软件安装

源码安装

linux软件都是用C/C++程序开发,所谓源码安装,是直接提供程序源代码,需要自行编译,然后生成目标可执行程序。类似提供的.java文件,需要自己编译.class,然后打包为jar,然后运行。源代码形式的特点:操作复杂、编译时间长、极易出现问题、依赖关系复杂,比较适合于专门做linux系统开发的人员。

  1. 绝大多数开源软件都是直接以原码形式发布的

  2. 源代码一般会被打成.tar.gz的归档压缩文件

  3. 源代码需要编译成为二进制形式之后才能够运行使用

  4. 源代码基本编译流程:

1).configure 检查编译环境;

2)make对源代码进行编译;

3)make insall 将生成的可执行文件安装到当前计算机中

RPM安装

RPM 是 LINUX 下的一种软件的可执行程序,你只要安装它就可以了。这种软件安装包通常是一个RPM包(Redhat Linux Packet Manager,就是Redhat的包管理器),后缀是.rpm。RPM是Red Hat公司随Redhat Linux推出了一个软件包管理器,通过它能够更加轻松容易地实现软件的安装。

  1. 安装软件:执行rpm -ivh rpm包名,如:rpm -ivh apache-1.3.6.i386.rpm

  2. 升级软件: 执行rpm -Uvh rpm包名。

  3. 卸载安装: 执行rpm -e rpm包名。

  4. 查询软件包的详细信息:执行rpm -qpi rpm包名

  5. 查询某个文件是属于那个rpm包的:执行rpm -qf rpm包名

  6. 查该软件包会向系统里面写入哪些文件:执行 rpm -qpl rpm包名

一般使用步骤如下:

rpm –i software.rpm(安装);
rpm -e software.rpm(卸载);
rpm –U software.rpm(升级形式安装);
rpm –ivh http://www.linuxcast.net/software.rpm(支持通过http\ftp协议形式安装)

rpm软件包形式的管理虽然方便,但是需要手工解决软件包的依赖关系。很多时候安装一个软件安装一个软件需要安装1个或者多个其他软件,手动解决时,很复杂,yum可以轻松解决这些问题。

YUM安装

yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的软件包管理器,简单理解Yum是rpm的前端程序。它能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。

yum仓库用来存放所有的现有的.rpm包,当使用yum安装一个rpm包时,需要依赖关系,会自动在仓库中查找依赖软件并安装。仓库可以是本地的,也可以是HTTP、FTP、nfs形式使用的集中地、统一的网络仓库。

其特点总结如下:

  1. 自动解决依赖关系

  2. 可以对rpm进行分组,基于组进行安装操作

  3. 引入仓库概念,支持多个仓库

  4. 配置简单

常规使用如下:

# yum install 安装;
# yum remove卸载;
# yum update 升级制定软件

本地安装

把需要的软件下载到linux主机,在主机上直接本地安装

安装软件介绍

服务/软件 端口 备注
jdk8 - JAVA的编译和运行环境
mysql/mariadb 3306 持久化关系型数据库
tomcat 8080 服务器
nginx 80 反向代理服务器

scp 命令上传 (命令是在Windows机器或mac机器上执行)

#scp 源码文件路径  目标文件路径
# 把本地文件上传到服务器 (当前Windows系统目录)
scp ./*.* [email protected]:~/soft
# 把远程服务器用户目录/soft下所有文件,下载到本地
scp [email protected]:~/soft/*.* ./

1、安装jdk【rpm安装】

rpm安装,能自动配置环境变量。

1)查看当前linux系统是否已经安装java

输入 rpm -qa | grep java

如果有已经安装的jdk ,需要使用以下命令删除

2) 卸载JDK

rpm -e --nodeps

3)安装jdk

 cd ~/soft
 rpm -ivh jdk-8u181-linux-x64.rpm

4)java -version测试是否成功

  java -version

展示以下内容代表OK

  java version "1.8.0_181"
  Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
  Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

2、安装mysql(mariadb)【yum】

MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB

1)查看CentOS自带的mysql

输入 rpm -qa | grep mysql

2)将自带的mysql卸载

rpm -e --nodeps

3)yum安装

yum -y install mariadb-server

4)启动mysql

systemctl start mariadb

5)设置root密码

注:这只是设置root用户在本机(linux)登录时的密码

mysqladmin -u root password 'root'  

6)进入mysql

mysql -u root -p

备注:输入密码:root

进入到数据库的执行命令行里面了。

7)  进入mysql,并执行下面sql

保证密码和本地一致

下面的话在mysql数据库里面里面执行

  -- 查看当前的数据库
show databases;
  -- 打开mysql
use mysql ;
  -- 查看所有表
show tables;
​
  -- 我们不用ipv6的地址,直接把host改为%,表示所有客户端都可以连接;同时设置密码为root
update user set host='%' ,password=password("root") where user='root' and host = '::1' ;
  -- 刷新后才能生效
flush privileges;

退出数据库命令操作

exit;
  1. 开放端口号

# 开放端口命令
firewall-cmd --zone=public --add-port=3306/tcp --permanent
#重新加载配置
firewall-cmd --reload
  1. 测试远程连接

使用数据库客户端,输入VMIP地址,输入Mysql的用户名和密码,如图

1.使用IDEA数据库客户端插件

2.输入数据库连接信息

3、配置tomcat【解压缩】

项目部署需要tomcat , 配置端口号。

  1. 下面需要使用uzip命令(根据当前系统情况而定,不是必须),先安装

#获取安装列表
yum list | grep zip/unzip
​
#提示输入时,请输入y
yum install zip
​
#提示输入时,请输入y
yum install unzip 

解压tomcat压缩包到 /app 目录下

cd ~/soft
#解压缩到当前
unzip apache-tomcat-8.5.47.zip
#移动到 /usr/local下
mv apache-tomcat-8.5.47 /usr/local/

启动apache-tomcat-8.5.47

 #确保启动文件有可执行权限,先修改权限
chmod 755 /usr/local/apache-tomcat-8.5.47/bin/*.sh
 #启动
/usr/local/apache-tomcat-8.5.47/bin/startup.sh

开放8080端口

# 开端口命令
firewall-cmd --zone=public --add-port=8080/tcp --permanent
#重新加载配置
firewall-cmd --reload

测试tomcat

在浏览器输入:http://192.168.188.128:8080/

安装Git及Maven

1.安装git【源码安装】

cd ~/soft
# 安装依赖环境
yum -y install zlib-devel curl-devel openssl-devel perl cpio expat-devel gettext-devel openssl zlib autoconf tk perl-ExtUtils-MakeMaker
# 解压缩到当前
tar -zxvf git_v2.4.0.tar.gz 
# 进入目录
cd git-2.4.0
# 配置并编译
autoconf
# 检验相关依赖,设置安装路径
./configure --prefix=/usr/local/git
make && make install

默认安装在 /usr/local/bin,把/usr/local/bin放在系统环境变量或当前用户环境变量,操作如下:

路径:/usr/local/git/bin:

vim ~/.bash_profile  #加入系统环境变量
source ~/.bash_profile #加载配置文件
git --version #查看版本

Linux_第102张图片

备注:这个路径一定写在系统路径的前面,可以覆盖系统默认的git。

2.安装maven【解压缩即可】

# 解压缩到/usr/local下
unzip -d /usr/local apache-maven-3.6.3-bin.zip
# 编辑配置文件,把 /usr/local/apache-maven-3.6.3,添加到系统环境变量
vim ~/.bash_profile  #加入系统环境变量
source ~/.bash_profile #加载配置文件
# 查看maven版本
mvn -v

路径:/usr/local/apache-maven-3.6.3

5、安装Nginx 【源码安装】

Nginx* (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日,2011年6月1日,nginx 1.0.4发布。

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

  • 安装前准备

#安装Nginx依赖环境,-y表示所有提示默认选择y
#nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库:
yum -y install pcre pcre-devel  
#nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库:
yum -y install zlib zlib-devel  
#nginx不仅支持http协议,还支持https,所以需要在linux安装openssl库:
yum -y install openssl openssl-devel
# 安装gcc编译环境
yum -y install gcc gcc-c++ autoconf automake make
  • 源码安装

    #解压缩nginx
    tar -xvf nginx-1.14.2.tar.gz 
    #进入nginx目录
    cd nginx-1.14.2
    #安装配置 
    ./configure  
    #编译
    make     
    # 安装就是把可执行文件复制到/usr/loca/nginx下
    make install   
   
> 安装成功之后,就会在/usr/local下多出了一个nginx目录.
   
- 使用Nginx
​
   ```shell
 #进入nginx的sbin目录
   cd /usr/local/nginx/sbin
#在sbin目录下启动
   ./nginx
    #在sbin目录下停止----需要再用
  ./nginx -s stop
  #在sbin目录下重写加载--需要再用
  ./nginx -s reload
  
  #修改端口(默认端口80)---需要再用
  vim /usr/local/nginx/conf/nginx.conf 配置文件
  • 开端口命令

#开放端口
firewall-cmd --zone=public --add-port=80/tcp --permanent
#重新加载配置
firewall-cmd --reload
#查看是否有nginx的线程是否存在
ps -ef | grep nginx
netstat -an -t -u | grep 80

在浏览器输入:http://192.168.188.128/

Linux_第103张图片

6.安装redis数据库 【源码安装】

  • 解压缩redis

    • tar -xvf redis-3.2.9.tar.gz -C /usr/local

  • make命令编译redis的C语言源码

    • 进入解压后的redis目录下的src目录

    • 输入make命令即可

      Linux_第104张图片

      ./redis-server 服务器

      ./redis-cli 客户端

    注意:可以把编译后的可执行程序可移动到自定义目录

    • 在redis 目录下创建bin目录,把编译后的服务器、客户端、配置文件copy到此目录下

      • cd /usr/local/redis-3.2.9

      • mkdir bin

      • cp ./src/redis-server ./bin

      • cp ./src/redis-cli ./bin

      • cp ./redis.conf ./bin

  • 启动redis服务器

    # 进入bin目录
    cd bin
    # 启动
    ./redis-server
  • 其它指令和配置

    #1. 后台运行 指令后面带 & 代表后台运行
    ./redis-server &  
    #2. 运行远程访问 
    #   使用vi编辑,打开redis.conf文件 (以下是在配置文件中修改)
    #==============
    # 注释如下这行,目前仅运行127.0.0.1访问
    bind 127.0.0.1
    #  开启密码访问模式
    requirepass pass
    # 开启守护进程,允许redis可以后台启动
    daemonize yes
    #===============
    #3. 指定配置文件,启动redis    
    ./redis-server redis.conf 
    ​
    #4. 启动redis客户端和关闭服务器
    ./redis-cli
    ./redis-cli shutdown
    #5.开放端口
    firewall-cmd --zone=public --add-port=6379/tcp --permanent
    #重新加载配置
    firewall-cmd --reload
    #查看是否有nginx的线程是否存在
    ps -ef | grep nginx
    netstat -an -t -u | grep 6379

部署资料中的SpringBoot项目,部署前先把数据库安装好,然后再把项目的jar包上传到服务器中,然后运行jar包即可。

  1. 确认当前数据库状态

systemctl status mariadb

Linux_第105张图片

启动数据库

systemctl start mariadb

启动后再次通过systemctl status mariadb命令查看,确保数据库已经启动

Linux_第106张图片

  1. 确保数据库已启动后,通过Idea连接此数据库。

注意,此处的连接地址,是虚拟机中CentOS的IP地址

Linux_第107张图片

  1. 执行资料中提供的sql文件,创建此项目需要的schema

Linux_第108张图片

执行后查看连接中的schema,确保执行成功

Linux_第109张图片

  1. 修改项目中配置文件的数据库和连接地址,修改为虚拟机中数据库的地址

Linux_第110张图片

  1. 修改后运行项目,确保访问页面可以正常访问数据,访问地址:http://localhost:8080/pages/books.html

Linux_第111张图片

  1. 执行打包命令,生成jar包

Linux_第112张图片

  1. 把jar包上传到虚拟机中

  1. 进入jar包所在路径,执行java -jar命令

此处java -jar 是前台启动,如果退出窗口的话会关闭java程序

如果需要后台启动需要执行后台启动命令

后台启动命令

nohup java -jar boot_books-1.0-SNAPSHOT.jar &

后台启动并输出日志命令

nohup java -jar boot_books-1.0-SNAPSHOT.jar &> books.log &

  1. 输入访问地址,测试程序是否部署成功,访问地址为虚拟机IP地址+端口号+地址

Linux_第113张图片

四、Nginx反向代理

正向代理

正向代理类似一个中转站,代理内部访问外部资源。

举个例子:

  我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,它能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从那个网站的角度来看,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

注意:客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的IP地址,还有代理程序的端口。

总结来说:正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。

正向代理的用途:

   1. 访问原来无法访问的资源,如google
   2. 可以做缓存,加速访问资源
   3. 对客户端访问授权,上网进行认证
   4. 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理的作用

  1. 保证内网的安全,可以使用反向代理提供防火墙(WAF)功能,阻止web攻击。大型网站,通常将反向代理作为公网访问地址,Web服务器是内网。

  2. 负载均衡,通过反向代理服务器来优化网站的负载。当大量客户端请求代理服务器时,反向代理可以集中分发不同用户请求给不同的weab服务器进行处理请求。(本阶段不实现,负载均衡技术项目阶段讲解)

反向代理配置

  1. 修改配置文件

vim /usr/local/nginx/conf/nginx.conf

以下是被修订过的nginx.conf,将所有访问到nginx80端口的路径是/开头的请求,都转发到webcase代表的反向代理机群,默认是请求其中一台。

http{
    upstream bookssm{
        server 127.0.0.1:8080;
        #server 192.168.200.129:8080;
    }
    server {
        listen       80;
        server_name  localhost;
        location / {
             root html;
             #proxy_pass http://192.168.200.138:8080
             proxy_pass http://bookssm;
             index index.html index.htm;
        }
	}  
}
  • http块 一个http处理模块,可进行http的相关参数配置,内可以包含多个server块;

  • upstream块 配置反向代理及负载均衡,可以写多个upstream块,是定义在server块前面。

    • server localhost:8080; localhost可以指向网络任何一台主机。

  • server块 包含在http{}内部,每一个server{}都是一个虚拟主机(站点)监听

    • listen 监听端口

    • server_name 用于与http请求header头部的Host匹配

    • location 路径配置,符合某个路径执行块内规则

      • / 代表根下资源

        • root html 是根下的资源,可以从html目录获取。

        • index 默认页面(不输入网页时,默认访问页)

        • proxy_pass 反向代理,请求转发给 webcase所代表的主机群

  1. 重启服务器

/usr/local/nginx/sbin/nginx -s reload
  1. 测试访问

、Linux系统操作

1. 磁盘目录查看

  • pwd 显示当前在哪个目录

  • clear 清屏

  • ls:查看目录

    • 参数 -a 显示全部,包含隐藏

    • 参数 -l 列表形式显示

    ls -l 列表展示

    • “d”开头是目录,

    • “-” 开头是文件,

    • “l” 开头是链接文件

    ls -a 查看隐藏文件

    • . 开头的是隐藏文件或目录

    ls -la 列表展示,包含隐藏文件 简写命令是 ll -a 。

2.目录切换命令

  • cd usr 切换到该目录下usr目录

  • cd .. 切换到上一层目录

  • cd / 切换到系统根目录

  • cd ~ (波浪号 tilde) 切换到用户主目录

  • cd - 切换到上一个所在目录

    注意:

    • 绝对路径: 从根开始的,都称为绝对路径

      cd /etc: 进入根目录下的etc

    • 相对路径:从当前开始的,都称为相对路径

      cd etc: 进入当前目录下的etc :

      cd ./etc 同上

      cd ../root 进入当前上一级目录 ,.. 代表上一级目录

    输入目录时,使用tab,系统会智能提示

3. 磁盘文件创建

创建空文件:touch

  • touch:创建新文件命令 touch 文件名 默认创建的空文件。

添加内容到文件:echo

  • echo "内容" > a.txt 添加内容到文件,会覆盖

  • echo "内容" >> a.txt 追加内容到文件,追加到尾部

  • cat 文件 显示文件内容

  • cat a.txt >> b.txt a文件追加到b文件

备注:

echo $变量 显示变量的值

4. 磁盘文件及目录操作

linux操作系统命令格式: 命令 -[参数]

增加:mkdir

mkdir 目录名字 [目录名列表],效果如下:

  • mkdir a 在当前下创建a

  • mkdir test/a1 在 test下创建a1

  • mkdir b c d 在当前下同时创建 b、c、d目录

注意:不能跨级创建子目录

修改:mv

mv 文件或目录名 目标文件或目录名,效果如下:

  • 文件操作 mv a.txt b.txt : b.txt不存在即为重命名,存在会提示是否覆盖

  • 目录操作 mv test tmp :tmp不存在即为重命名,存在为移动效果

  • 文件对目录 mv a.txt ./tmp 移动文件到指定目录

复制:cp

cp [参数] 源文件或目录,目标文件或目录

参数: -r 递归

  • 单文件操作 cp a.txt a.txt.bak 在当前下复制一个文件

  • 多文件操作 cp ./web/* ./test 把web下的所有文件复制到test下

  • 递归操作 cp -r ./web/* ./test 把web下的所有文件及子目录复制到test下

删除:rm

rm [参数] 删除文件目录命令

参数: -r 递归 -f 忽略询问

  • rm a.txt 删除当前下的文件,会询问提示

  • rm -f a.txt 不询问直接删除

  • rm -rf ./test 递归删除test下的所有内容,包含test本身

  • rm -rf ./test/* 递归删除test下的所有内容,但是test不删除

    注意:删除一个目录,必须是rm -rf,否则不能删除

搜索:find

find 搜索位置 -name 字符串

  • find / - name 'java' 查java

  • find / -name '*redis' 查找含有redis的

5. 磁盘文件及目录权限

权限概述

权限是Linux中的重要概念,每个文件/目录等都具有权限,通过ls -l命令我们可以 查看某个目录下的文件或目录的权限

示例:在随意某个目录下ls -l

Linux_第114张图片

Linux_第115张图片

  • 文件的类型:

    • d:代表目录

    • -:代表文件

    • l:代表链接(可以认为是window中的快捷方式)

  • 后面的9位分为3组,每3位置一组,分别代表属主的权限,与当前用户同组的 用户的权限,其他用户的权限

    • r:代表权限是可读,r也可以用数字4表示

    • w:代表权限是可写,w也可以用数字2表示

    • x:代表权限是可执行,x也可以用数字1表示

Linux_第116张图片

权限设置

语法:chmod 数字或符号权限 [参数] 文件或目录

  • chmod u=rwx,g=rw,o=r aaa.txt

  • chmod 750 -R 文件或目录名 递归授权

  • chmod 755 文件或目录

  • chmod 777 -R 文件或目录

6. 文件内容浏览

  • cat命令 查看文件,只能显示文件最后一屏

    cat a.txt 查看文件全部内容

    注意:

    cat除了查看文件内容,还可以把文件内容进行合并

    cat a.txt >> b.txt 把a.txt文件输出到b.txt中

    比如:

    echo 'aaa' > a.txt

    echo 'bbb' > b.txt

    cat a.txt >> b.txt

  • more命令查询文件:分页查看所有内容,带百分比

    显示文件百分比,回车下一行,空格下一页,退出是Q

  • less命令查看文件:分页查看所有内容,带行号和百分比

    箭头上下代表上一行,下一行,空格显示下一页,退出是Q

    -N(大写) 显示行号

    -m 百分比

  • head/tail命令查看文件,支持显示的文件行数

    head 查看文件头部 内容

    tail 查看文件尾部内容

    -n 数字 代表行数

    -f 实时持续查看文件内容

7. 文件内容编辑(vi/vim)

  • vim:文件名

    适合快速修改纯文本文件,比如配置文件、属性文件、源文件等

  • vim编辑器有三种模式

    命令模式、编辑模式、底行模式,按ESC,退出当前模式,进入命令模式。

    • 命令模式

      刚刚进入是命令模式,从命令模式可进入编辑模式或底行模式。

      只接受命令关键字 其他字符不接受,通过输入相应的命令可以进入编辑模式

      dd:删除当前行

      yy:复制当前行

      p:粘贴

      整页翻页 ctrl-f、 f是forword , ctrl-b b就是backward

      shift+$是移动到行尾,0是移动到行首

    • 编辑模式

      进入编辑模式命令:i,o,a或者insert

      对文件进行内容编辑 任何字符都接受,内容编辑完毕之后 需要退回命令模式

      退回到命令模式,按ESC键

    • 底行模式

      在命令模式下,输入冒号 : ,进入底行模式。

      底行命令:

      • :wq,写入并退出,

      • :q! ,退出不保存

      • :set nu,显示行号

      • :set nu!,取消行号显示

      • :数字,定位行号

      • :/ 搜索字符,n是下一个,N是上一个

      • :noh 清除搜索高亮显示

  • vim编辑器使用过程关于vim使用过程:

    vim 文件-------->命令模式--------->输入i---------->编辑模式----------->编辑文件----------->按下Esc--------->命令模式--------->按下:---------->底行模式----------->输入wq保存并退出/q!强制退出不保存

8. 压缩文件管理

Linux中的打包文件一般是以.tar结尾的,压缩的命令一般是以.gz结尾的。而一般情况下打包和压缩是一起进行的,打包并压缩后的文件的后缀名一般.tar.gz。

tar命令:压缩和解压缩

  • 参数:-z 调用gzip压缩命令压缩

  • 参数:-c 打包文件

  • 参数:-C 在指定的目录解压缩

  • 参数:-v 显示命令的执行过程

  • 参数:-f 指定文件名

  • 参数:-x 解压缩

  • 示例:将test目录打成压缩包,压缩后文件名为 test.tar.gz

    • tar -zcvf test.tar.gz test

  • 示例:将test.tar.gz进行解压缩

    • tar -xvf test.tar.gz

    • tar -xvf test.tar.gz -C /usr/local 解压缩到指定的目录

zip命令 压缩命令

zip -r mydata.zip mydata #压缩mydata目录

zip -r abc123.zip abc 123.txt #把abc文件夹和123.txt压缩成为abc123.zip

unzip 解压缩命令

unzip -d /a/b filename.zip 将文件解压缩到/a/b目录里面

9.Linux系统命令

进程命令

ps命令:查看进程

  • 参数:-e 显示所有程序

  • 参数:-f 显示UID,PPIP

    ps -ef 显示所有进程

    UID :程序被该 UID(用户ID) 所拥有

    PID :就是这个程序的 ID

    PPID :则是其上级父程序的ID**

    C :CPU使用的资源百分比**

    STIME :系统启动时间**

    TTY :登入者的终端机位置**

    TIME :使用掉的CPU时间。**

    CMD :所下达的是什么指令**

kill命令:结束进程

参数:-9 强制杀死该进程

过滤命令

grep [option] 字符串或正则表达式 文件名

从指定文件,搜索匹配的字符串

-i 忽略大小写

  • 示例:

    grep -i test /etc/sudo.conf 中包含字符串“test”的内容,且忽略大小写

    grep '^d' /etc/sudo.conf 查找以d开头的数据

    A命令 |B命令 | C命令

将前一个命令的输出作为下一个命令的输入

可以任意组合,只要是上一级有内容输出,下一个管道就可以处理

  • ll | grep '^d' | grep '.d$'| grep '4月'

  • find / -name '*.log' | grep 'tomcat'

网络命令

查看IP

ifconfig 查看本机网络卡信息

测试网络

ping 查看与某台主机的连接情况

查看端口

netstat 查看本机被使用的端口号

参数:-a 显示所有连接

参数:-n 以网络IP地址代替名称

-t 显示tcp, -u 显示udp连接情况

常用

netstat -an -t -u | grep '8080'

lsof -i tcp:3306

重启关机命令

重启 reboot

关机 halt | shutdown

附录

安装iptables服务 【yum安装】

iptables是linux 系统自带的优秀且完全免费的基于包过滤的防火墙工具、它的功能十分强大、使用非常灵活、可以对流入、流出及流经服务器的数据包进行精细的控制。特别是它可以在一台非常低配置下跑的非常好。 centos系统,默认仅仅开放了22端口,其他端口需要使用iptables进行管理(开放、删除、保存规则等)

  • 安装iptables

yum install iptables-services
  • Linux_第117张图片

  • 添加规则 (比如开放8080端口)

    /sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT  
  • Linux_第118张图片

  • 保存规则

service iptables save
  • 配置开机启动

    把启动防火墙服务的命令,加入到开机启动的配置文件中即可。

    vim  /etc/profile
  • Linux_第119张图片

  • 查看与删除iptables中放行的规则

    #查看iptables列表,显示列表编号
    iptables -L -n --line-number
    Chain INPUT (policy ACCEPT)
    num  target     prot opt source               destination         
    1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 
    2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:3306 
    3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 
    4    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    #删除iptables列表中 编号为1的规则
    iptables -D INPUT 1
    

安装Mysql【yum安装】

  • yum命令安装

     yum -y install mysql-community-server

    如果出现如图所示,请参考【手动获取rpm文件】:

    • Linux_第120张图片

    • Linux_第121张图片

    需要下载205M的资源,需要根据网络情况,等待比较久的时间。

    安装完毕如下:

    • Linux_第122张图片

  • 手动获取rpm文件安装

    在线获取rpm包

    wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm

    安装下载的rpm文件

    rpm -ivh mysql-community-release-el7-5.noarch.rpm

    安装mysql-server

    yum install mysql-server 
  • 启动mysql服务

  service mysqld start
  • 查看初始密码【5.7版本执行如下命令,5.6版本,默认密码是空】

  grep "password" /var/log/mysqld.log

  • 登录mysql

  mysql -u root -p

输入初始密码,可以复制密码,并粘贴到输入密码的位置

  • 设置root密码

    1. 修改安全策略 (mysql5.7不允许设置比较简单的密码策略)

set global validate_password_policy=0;
set global validate_password_length=1;
  • Linux_第123张图片

2. 设置密码: set password = password('123456');

3. 授权远程连接

默认情况下mysql为安全起见,不支持远程登录mysql,所以需要设置开启远程登录mysql的权限

grant all privileges on *.* to 'root' @'%' identified by '123456';
flush privileges;
SET PASSWORD FOR 'root'@'%'= PASSWORD('123456');
  • Linux_第124张图片

  • 开放3306端口

    /sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT
    service iptables save

安装与配置JDK [解压缩安装]

  • tar -xvf 解开压缩包到指定目录

    • tar -xvf jdk-8u211-linux-x64.tar.gz -C /usr/local

  • 编辑配置文件,并配置环境变量

    全局配置或当前用户配置,二选一即可。

    全局配置文件: vim /etc/profile 或 用户配置文件 vim ~/.bash_profile 推荐前者。

    vim  /etc/profile

    将以下代码复制到profile文件中的末尾。

    #set java environment
    JAVA_HOME=/usr/local/jdk1.8.0_211/
    CLASSPATH=.:$JAVA_HOME/lib.tools.jar
    PATH=$JAVA_HOME/bin:$PATH
    export JAVA_HOME CLASSPATH PATH 

    保存并退出

  • 加载环境变量

    source /etc/profile 或 source .bash_profile ,推荐前者。

    source  /etc/profile

    不出现任何提示,说明环境加载成功。

  • 测试环境

    输入 java或javac ,出现如下提示即为环境配置成功

    • Linux_第125张图片

    如果出现:

    • 前面的路径没有设置正确,请重新检查profile文件设置的路径与磁盘路径是否一致

    • 重新执行 source /etc/profile

Git部署Web项目

1. 拉取代码

  1. 在Git仓库平台增加服务端的ssh公钥

    在服务端机器生成密钥对,使用ssh命令,生成的密钥默认放在用户目录的.ssh目录。

    #生成密钥,输入完成命令,默认回车即可。
    ssh-keygen -t rsa -C "[email protected]"
    # 查看用户目录下的隐藏目录
    ls -a ~/ 
    # 查看.ssh目录下的密钥
    ls ~/.ssh/ 
    # 查看公钥信息
    cat .ssh/id_rsa.pub 

    -C "[email protected]" 如果省略默认是当前主机名称

    Linux_第126张图片

    复制生成后的 ssh key,通过仓库主页 「管理」->「部署公钥管理」->「添加部署公钥」 ,添加生成的 public key 添加到仓库中。

    Linux_第127张图片

  2. 使用SSH方式,克隆Git仓库代码

    cd ~       #切换到用户目录
    git clone [email protected]:mobapp/webcase.git
    cd ~/webcase
    #git clone [email protected]:mobapp/study_springmvc_ssm.git  #SSH方式克隆代码
    #cd study_springmvc_ssm # 进入项目根目录
    git branch # 查看当前分支,默认是master分支
    git pull # 拉取最新代码 [第1次不用]
    git checkout master # 切换到主分支 [第1次不用]

2. 项目打包

使用mvn命令,自动打包当前项目,默认生成在工程目录的target下

cd ~/webcase
mvn clean package -Dmaven.test.skip=true

备注:第1次打包,会非常慢,因为需要下载依赖库,可以把本地已经下载好的仓库直接放在用户目录的.m2下。

1.上传本地maven仓库到服务器m2目录下

Linux_第128张图片

2.解压缩本地仓库

cd ~/.m2
unzip -o repository

Linux_第129张图片

备注:-o 覆盖解压缩

3.重新打包

cd ~/webcase
mvn clean package -Dmaven.test.skip=true

3. 项目部署

把War把部署到Tomcat

把生成的war包移动或复制到tomcat webapps目录下即可,注意文件名就是应用的名称。

# 把war包copy到webapp是目录下,并取名为springssm.war 
# \cp 是强制覆盖,一般第2次部署时,是不需要确认的,直接覆盖
# cp 如果遇到重名,会提示覆盖
#\cp ~/study_springmvc_ssm/target/springmvc_ssm.war /usr/local/apache-tomcat-8.5.47/webapps/springssm.war
\cp ./target/webcase.war /usr/local/apache-tomcat-8.5.47/webapps/
#启动Tomcat 默认不用重启是可以的
/usr/local/apache-tomcat-8.5.47/bin/startup.sh
# 查看访问日志
tail -f /usr/local/apache-tomcat-8.5.47/logs/localhost_access_log.2022-04-24.txt
  1. 访问测试

    http://192.168.200.138:8080/webcase/login.html

Git部署Boot项目

1. 拉取代码

cd ~       #切换到用户目录
git clone [email protected]:mobapp/spring-boot-mybatis.git  #SSH方式克隆代码
cd spring-boot-mybatis # 进入项目根目录
git branch # 查看当前分支,默认是master分支
git pull # 拉取最新代码 [第1次不用]
git checkout master # 切换到主分支 [第1次不用]

2. 项目打包

mvn clean package -Dmaven.test.skip=true

3. 项目启动

  1. 启动mysql数据库【前面已启动】

  2. 安装项目数据库【前面已安装,本项目与之前项目用的同一数据库】

  3. 初始化项目的工作目录

    # 在当前创建工作目录
    mkdir ~/springmvcboot
    # 进入工作目录
    cd ~/springmvcboot
  4. 启动项目

# 强制负责编译之后的jar包到工作目录
\cp ~/spring-boot-mybatis/target/springboot_ssm.jar ~/springmvcboot
# 后台启动boot项目
nohup java -jar springboot_ssm.jar --server.port=8088 --spring.profiles.active=pro >springboot_ssm_out.log 2>&1 &
# 查看启动日志
tail -f springboot_ssm_out.log
# 开放端口
firewall-cmd --zone=public --add-port=6379/tcp --permanent
#重新加载配置
firewall-cmd --reload
  • nohup:不挂断地运行命令,退出帐户之后继续运行相应的进程。

  • springboot_ssm_out.log:是nohup把command的输出重定向到当前目录的指定的文件中.

    即输出内容不打印到屏幕上,而是输出到”日志文件名.log”文件中。

  • 2>&1 2就是标准错误,1是标准输出

    该命令相当于把标准错误重定向到标准输出么。这里&相当于标准错误等效于标准输出,即把标准错误和标准输出同时输出到指定的“日志文件名.log”文件中。

  1. 访问测试

http://192.168.200.138:8088/user/queryAll

注意boot项目,默认是发布在web的根目录下的。SSM项目只要发布到webapps/ROOT下才发布到根目录

部署SpringMVC项目

部署之前的综合案例,部署前先把数据库安装好,然后再把项目的war包copy到tomcat安装目录即可。

1. 初始化项目数据库

  1. msyql客户端工具连接VM中的mysql

  2. 在客户端工具中初始化数据库脚本

CREATE SCHEMA `ssm_db` DEFAULT CHARACTER SET utf8mb4;

use `ssm_db`;

-- ----------------------------
-- Table structure for tbl_book
-- ----------------------------
DROP TABLE IF EXISTS `tbl_book`;
CREATE TABLE `tbl_book`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of tbl_book
-- ----------------------------
INSERT INTO `tbl_book` VALUES (1, '计算机理论', 'Spring实战 第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕');
INSERT INTO `tbl_book` VALUES (2, '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想');
INSERT INTO `tbl_book` VALUES (3, '计算机理论', 'Spring 5 设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式');
INSERT INTO `tbl_book` VALUES (4, '计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手');
INSERT INTO `tbl_book` VALUES (5, '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者');
INSERT INTO `tbl_book` VALUES (6, '计算机理论', 'Java核心技术 卷I 基础知识(原书第11版)', 'Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新');
INSERT INTO `tbl_book` VALUES (7, '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,大厂面试知识点全覆盖');
INSERT INTO `tbl_book` VALUES (8, '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉');
INSERT INTO `tbl_book` VALUES (9, '计算机理论', '零基础学Java(全彩版)', '零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术');
INSERT INTO `tbl_book` VALUES (10, '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
INSERT INTO `tbl_book` VALUES (11, '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍');
INSERT INTO `tbl_book` VALUES (12, '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');

以下是使用IDEA,初始化数据库:

Linux_第130张图片

Linux_第131张图片

2. 部署项目war包

  1. 使用IDEA打war包并上传到服务器

    1. 打包

    Linux_第132张图片

    1. 上传到服务器(注意:IP写自己的服务器)

  2. 停止当前的tomat服务器

    /usr/local/apache-tomcat-8.5.47/bin/shutdown.sh
  3. 上传war包到tomcat目录的webapps目录下

    (注意:IP写自己的服务器)

    scp book_ssm.war [email protected]:/app/apache-tomcat-8.5.47/webapps

    备注:SCP会自动覆盖之前上传的文件,Tomcat自动解压缩覆盖之前的文件

  4. 启动Tomcat服务器

    /usr/local/apache-tomcat-8.5.47/bin/startup.sh
  5. 浏览器测试

    http://192.168.188.128:8080/book_ssm/pages/books-tomcat.html

如果显示不正常,请查看日志:

tail -f  /usr/local/apache-tomcat-8.5.47/logs/catalina.out

瑞吉外卖项目优化-day08

课程内容

  • 前后端分离开发

  • Yapi

  • Swagger

  • 项目部署

前言

当前项目中,前端代码和后端代码混合在一起,是存在问题的,存在什么问题呢?

主要存在以下几点问题:

1). 开发人员同时负责前端和后端代码开发,分工不明确

2). 开发效率低

3). 前后端代码混合在一个工程中,不便于管理

4). 对开发人员要求高(既会前端,又会后端),人员招聘困难

为了解决上述提到的问题,现在比较主流的开发方式,就是前后端分离开发,前端人员开发前端的代码,后端开发人员开发服务端的业务功能,分工明确,各司其职。我们本章节,就是需要将之前的项目进行优化改造,变成前后端分离开发的项目。

1. 前后端分离开发

1.1 介绍

前后端分离开发,就是在项目开发过程中,对于前端代码的开发由专门的前端开发人员负责,后端代码则由后端开发人员负责,这样可以做到分工明确、各司其职,提高开发效率,前后端代码并行开发,可以加快项目开发进度。

目前,前后端分离开发方式已经被越来越多的公司所采用,成为当前项目开发的主流开发方式。

前后端分离开发后,从工程结构上也会发生变化,即前后端代码不再混合在同一个maven工程中,而是分为 前端工程后端工程

Linux_第133张图片

前后端分离之后,不仅工程结构变化,后期项目上线部署时,与之前也不同:

1). 之前: 前后端代码都混合在一起,我们只需要将前端和后端的代码统一打成jar包,直接运行就可以了。

2). 现在: 拆分为前后端分离的项目后,最终部署时,后端工程会打成一个jar包,运行在Tomcat中(springboot内嵌的tomcat)。前端工程的静态资源,会直接部署在Nginx中进行访问。

1.2 开发流程

前后端分离开发后,面临一个问题,就是前端开发人员和后端开发人员如何进行配合来共同开发一个项目?可以按照如下流程进行:

Linux_第134张图片

1). 定制接口: 这里所说的接口不是我们之前在service, mapper层定义的interface; 这里的接口(API接口)就是一个http的请求地址,主要就是去定义:请求路径、请求方式、请求参数、响应数据等内容。(具体接口文档描述的信息, 如上图)

2). 前后端并行开发: 依据定义好的接口信息,前端人员开发前端的代码,服务端人员开发服务端的接口; 在开发中前后端都需要进行测试,后端需要通过对应的工具来进行接口的测试,前端需要根据接口定义的参数进行Mock数据模拟测试。

3). 联调: 当前后端都开发完毕并且自测通过之后,就可以进行前后端的联调测试了,在这一阶段主要就是校验接口的参数格式。

4). 提测: 前后端联调测试通过之后,就可以将项目部署到测试服务器,进行自动化测试了。

1.3 前端技术栈

1). 开发工具

Visual Studio Code (简称VsCode)

Hbuilder

2). 技术框架

A. Node.js: Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。(类似于java语言中的JDK)。

B. Vue : 目前最火的的一个前端javaScript框架。

C. ElementUI: 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库,通过ElementUI组件可以快速构建项目页面。

D. Mock: 生成随机数据,拦截 Ajax 请求,前端可以借助于Mock生成测试数据进行功能测试。

E. Webpack: webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler),分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

2. Yapi

2.1 介绍

YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击操作就可以实现接口的管理。

YApi让接口开发更简单高效,让接口的管理更具可读性、可维护性,让团队协作更合理。

源码地址: GitHub - YMFE/yapi: YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台

官方文档: YApi 接口管理平台

要使用YApi,项目组需要自己进行部署,在本项目中我们可以使用课程提供的平台进行测试。L

域名: https://mock-java.itheima.net/

2.2 使用

2.2.1 准备

注册账号,登录平台

2.2.2 定义接口

登录到Yapi平台之后,我们可以创建项目,在项目下创建接口分类,在对应的分类中添加接口。

1). 创建项目

Linux_第135张图片

Linux_第136张图片

2). 添加分类

在当前项目中,有针对于员工、菜品、套餐、订单的操作,我们在进行接口维护时,可以针对接口进行分类,如果没有对应的分类,我们自己添加分类。

Linux_第137张图片

3). 添加接口

Linux_第138张图片

接口基本信息录入之后,添加提交,就可以看到该接口的基本信息:

Linux_第139张图片

但是目前,接口中我们并未指定请求参数,响应数据等信息,我们可以进一步点击编辑,对该接口 详情进行编辑处理。

Linux_第140张图片

Linux_第141张图片

Linux_第142张图片

4). 运行接口

Yapi也提供了接口测试功能,当我们接口编辑完毕后,后端服务的代码开发完毕,启动服务,就可以使用Yapi进行接口测试了。

Linux_第143张图片

注意: 由于菜品分页查询接口,是需要登录后才可以访问的,所以在测试该接口时,需要先请求员工管理接口中的登录接口,登录完成后,再访问该接口。

插件安装(运行时,如果是谷歌浏览器需要安排调试插件):

Linux_第144张图片

插件安装,可参考:chrome 安装 yapi 扩展教程 - 掘金,使用的插件已在资料中。

在Yapi平台中,将接口文档定义好了之后,前后端开发人员就需要根据接口文档中关于接口的描述进行前端和后端功能的开发。

2.2.3 导出接口文档

在Yapi平台中我们不仅可以在线阅读文档,还可以将Yapi中维护的文档直接导出来,可以导出md,json,html格式,在导出时自行选择即可 。

Linux_第145张图片

而在导出的html文件或md文件中,主要描述的就是接口的基本信息, 包括: 请求路径、请求方式、接口描述、请求参数、返回数据等信息。展示形式如下:

Linux_第146张图片

2.2.4 导入接口文档

上述我们讲解了接口文档的导出,我们也可以将外部的接口文档导入到Yapi的平台中,这样我们就不用一个接口一个接口的添加了。我们可以将课程资料中提供的json格式的接口文档直接导入Yapi平台中来。

Linux_第147张图片

导入过程中出现的确认弹窗,选择"确认"。

Linux_第148张图片

导入成功之后,我们就可以在Yapi平台查看到已导入的接口。

Linux_第149张图片

3. Swagger

3.1 介绍

官网:API Documentation & Design Tools for Teams | Swagger

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。功能主要包含以下几点:

A. 使得前后端分离开发更加方便,有利于团队协作

B. 接口文档在线自动生成,降低后端开发人员编写接口文档的负担

C. 接口功能测试

使用Swagger只需要按照它的规范去定义接口及接口相关的信息,再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,以及在线接口调试页面等等。

直接使用Swagger, 需要按照Swagger的规范定义接口, 实际上就是编写Json文件,编写起来比较繁琐、并不方便, 。而在项目中使用,我们一般会选择一些现成的框架来简化文档的编写,而这些框架是基于Swagger的,如knife4j。knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。而我们要使用kinfe4j,需要在pom.xml中引入如下依赖即可:


    com.github.xiaoymin
    knife4j-spring-boot-starter
    3.0.2

3.2 使用方式

接下来,我们就将我们的项目集成Knife4j,来自动生成接口文档。这里我们还是需要再创建一个新的分支v1.2,在该分支中进行knife4j的集成,集成测试完毕之后,没有问题,我们再将v1.2分支合并到master。

使用knife4j,主要需要操作以下几步:

1). 导入knife4j的maven坐标


    com.github.xiaoymin
    knife4j-spring-boot-starter
    3.0.2

2). 导入knife4j相关配置类并设置静态资源访问

这里我们就不需要再创建一个新的配置类了,我们直接在WebMvcConfig配置类中声明即可。

A. 在该配置类中加上两个注解 @EnableSwagger2 @EnableKnife4j ,开启Swagger和Knife4j的功能。

B. 在配置类中声明一个Docket类型的bean, 通过该bean来指定生成文档的信息。

C. 由于Swagger生成的在线文档中,涉及到很多静态资源,这些静态资源需要添加静态资源映射,否则接口文档页面无法访问。因此需要在 WebMvcConfig类中的addResourceHandlers方法中增加如下配置。

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

@Slf4j
@Configuration
@EnableSwagger2
@EnableKnife4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
    
    @Autowired
	private ObjectMapper objectMapper;

    /**
     * 设置静态资源映射
     * 由于Swagger生成的在线文档中,涉及到很多静态资源,这些静态资源需要添加静态资源映射,否则接口文档页面无法访问。因此需要在 WebMvcConfig类中的addResourceHandlers方法中增加如下配置。
     * @param registry
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始进行静态资源映射...");
        
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
		registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

    /**
     * 扩展mvc框架的消息转换器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List> converters) {
        log.info("扩展消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        //messageConverter.setObjectMapper(new JacksonObjectMapper());
        messageConverter.setObjectMapper(objectMapper);
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0,messageConverter);
    }

    @Bean
    public Docket createRestApi() {
        // 文档类型
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.itheima.reggie.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    // // springfox.documentation.service.ApiInfo
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("瑞吉外卖")
                .version("1.0")
                .description("瑞吉外卖接口文档")
                .build();
    }
}

注意: Docket声明时,指定的有一个包扫描的路径,该路径指定的是Controller所在包的路径。因为Swagger在生成接口文档时,就是根据这里指定的包路径,自动的扫描该包下的@Controller, @RestController, @RequestMapping等SpringMVC的注解,依据这些注解来生成对应的接口文档。

3). 在LoginCheckFilter中设置不需要处理的请求路径

需要将Swagger及Knife4j相关的静态资源直接放行,无需登录即可访问,否则我们就需要登录之后,才可以访问接口文档的页面。

在原有的不需要处理的请求路径中,再增加如下链接:

"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"

Linux_第150张图片

3.3 查看接口文档

经过上面的集成配置之后,我们的项目集成Swagger及Knife4j就已经完成了,接下来我们可以重新启动项目,访问接口文档,访问链接为: http://localhost:8080/doc.html

Linux_第151张图片

我们可以看到,在所有的Controller中提供的所有的业务增删改查的接口,全部都已经自动生成了,我们通过接口文档可以看到请求的url、请求方式、请求参数、请求实例、响应的参数,响应的示例。 并且呢,我们也可以通过这份在线的接口文档,对接口进行测试。

Linux_第152张图片

注意: 由于我们服务端的Controller中的业务增删改查的方法,都是必须登录之后才可以访问的,所以,我们在测试时候,也是需要先访问登录接口。登录完成之后,我们可以再访问其他接口进行测试。

我们不仅可以在浏览器浏览生成的接口文档,Knife4j还支持离线文档,对接口文档进行下载,支持下载的格式有:markdown、html、word、openApi。

Linux_第153张图片

3.4 常用注解

3.4.1 问题说明

在上面我们直接访问Knife4j的接口文档页面,可以查看到所有的接口文档信息,但是我们发现,这些接口文档分类及接口描述都是Controller的类名(驼峰命名转换而来)及方法名,而且在接口文档中,所有的请求参数,响应数据,都没有中文的描述,并不知道里面参数的含义,接口文档的可读性很差。

Linux_第154张图片

3.4.2 注解介绍

为了解决上述的问题,Swagger提供了很多的注解,通过这些注解,我们可以更好更清晰的描述我们的接口,包含接口的请求参数、响应数据、数据模型等。核心的注解,主要包含以下几个:

注解 位置 说明
@Api 加载Controller类上,表示对类的说明
@ApiModel 类(通常是实体类) 描述实体类的作用
@ApiModelProperty 属性 描述实体类的属性
@ApiOperation 方法 说明方法的用途、作用
@ApiImplicitParams 方法 表示一组参数说明
@ApiImplicitParam 方法 用在@ApiImplicitParams注解中,指定一个请求参数的各个方面的属性

3.4.3 注解测试

1). 实体类

可以通过 @ApiModel , @ApiModelProperty 来描述实体类及属性

@Data
@ApiModel("套餐")
public class Setmeal implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("主键")
    private Long id;
    
    //分类id
    @ApiModelProperty("分类id")
    private Long categoryId;
    
    //套餐名称
    @ApiModelProperty("套餐名称")
    private String name;
​
    //套餐价格
    @ApiModelProperty("套餐价格")
    private BigDecimal price;
​
    //状态 0:停用 1:启用
    @ApiModelProperty("状态")
    private Integer status;
​
    //编码
    @ApiModelProperty("套餐编号")
    private String code;
​
    //描述信息
    @ApiModelProperty("描述信息")
    private String description;
​
    //图片
    @ApiModelProperty("图片")
    private String image;
​
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
​
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
​
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
​
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
}

2). 响应实体R

@Data
@ApiModel("返回结果")
public class R<T> implements Serializable{
​
    @ApiModelProperty("编码")
    private Integer code; //编码:1成功,0和其它数字为失败
​
    @ApiModelProperty("错误信息")
    private String msg; //错误信息
​
    @ApiModelProperty("数据")
    private T data; //数据
​
    @ApiModelProperty("动态数据")
    private Map map = new HashMap(); //动态数据
    
    //省略静态方法 ....
}    

3). Controller类及其中的方法

描述Controller、方法及其方法参数,可以通过注解: @Api, @APIOperation, @ApiImplicitParams, @ApiImplicitParam

@RestController
@RequestMapping("/setmeal")
@Slf4j
@Api(tags = "套餐相关接口")
public class SetmealController {
​
    @Autowired
    private SetmealService setmealService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SetmealDishService setmealDishService;
​
    /**
     * 新增套餐
     * @param setmealDto
     * @return
     */
    @PostMapping
    @CacheEvict(value = "setmealCache",allEntries = true)
    @ApiOperation(value = "新增套餐接口")
    public R<String> save(@RequestBody SetmealDto setmealDto){
        log.info("套餐信息:{}",setmealDto);
​
        setmealService.saveWithDish(setmealDto);
​
        return R.success("新增套餐成功");
    }
​
    /**
     * 套餐分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    @ApiOperation(value = "套餐分页查询接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "页码",required = true),
            @ApiImplicitParam(name = "pageSize",value = "每页记录数",required = true),
            @ApiImplicitParam(name = "name",value = "套餐名称",required = false)
    })
    public R<Page> page(int page,int pageSize,String name){
        //分页构造器对象
        Page<Setmeal> pageInfo = new Page<>(page,pageSize);
        Page<SetmealDto> dtoPage = new Page<>();
​
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        //添加查询条件,根据name进行like模糊查询
        queryWrapper.like(name != null,Setmeal::getName,name);
        //添加排序条件,根据更新时间降序排列
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
​
        setmealService.page(pageInfo,queryWrapper);
​
        //对象拷贝
        BeanUtils.copyProperties(pageInfo,dtoPage,"records");
        List<Setmeal> records = pageInfo.getRecords();
​
        List<SetmealDto> list = records.stream().map((item) -> {
            SetmealDto setmealDto = new SetmealDto();
            //对象拷贝
            BeanUtils.copyProperties(item,setmealDto);
            //分类id
            Long categoryId = item.getCategoryId();
            //根据分类id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category != null){
                //分类名称
                String categoryName = category.getName();
                setmealDto.setCategoryName(categoryName);
            }
            return setmealDto;
        }).collect(Collectors.toList());
​
        dtoPage.setRecords(list);
        return R.success(dtoPage);
    }
​
    /**
     * 删除套餐
     * @param ids
     * @return
     */
    @DeleteMapping
    @CacheEvict(value = "setmealCache",allEntries = true)
    @ApiOperation(value = "套餐删除接口")
    public R<String> delete(@RequestParam List<Long> ids){
        log.info("ids:{}",ids);
​
        setmealService.removeWithDish(ids);
​
        return R.success("套餐数据删除成功");
    }
​
    /**
     * 根据条件查询套餐数据
     * @param setmeal
     * @return
     */
    @GetMapping("/list")
    @Cacheable(value = "setmealCache",key = "#setmeal.categoryId + '_' + #setmeal.status")
    @ApiOperation(value = "套餐条件查询接口")
    public R<List<Setmeal>> list(Setmeal setmeal){
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getCategoryId() != null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus() != null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
​
        List<Setmeal> list = setmealService.list(queryWrapper);
​
        return R.success(list);
    }
}
​

4). 重启服务测试

我们上述通过Swagger的注解,对实体类及实体类中的属性,以及Controller和Controller的方法进行描述,接下来,我们重新启动服务,然后看一下自动生成的接口文档有何变化。

Linux_第155张图片

在接口文档的页面中,我们可以看到接口的中文描述,清晰的看到每一个接口是做什么的,接口方法参数什么含义,参数是否是必填的,响应结果的参数是什么含义等,都可以清楚的描述出来。

总之,我们要想清晰的描述一个接口,就需要借助于Swagger给我们提供的注解。

4. 项目部署

在本章节,我们要做的是项目的部署,包含前端项目的部署,及后端项目的部署。

4.1 部署架构

Linux_第156张图片

PC端: 主要是为餐厅的员工及管理员使用的后台管理系统,对分类、菜品、套餐信息进行维护。

移动端: 可以基于微信公众号或小程序实现,我们课上并未实现,这部分的工作是前端开发人员需要开发的。

防火墙:硬件产品,让访问服务器更加安全

前端部署服务器: Nginx(反向代理)

后端部署服务器: 项目部署服务器

4.2 环境说明

具体的服务器的软件安装如下:

服务器 软件 名称
Nginx服务器 Nginx(部署前端项目、配置反向代理)
项目部署服务器 JDK1.8、Git、Maven
数据库服务器 MySQL数据库
Redis服务器 Redis(缓存中间件)

以上需要的软件安装,可以参考

4.3 前端项目部署

1). 在服务器A中安装Nginx,将课程资料中的静态资源目录上传到Nginx的html目录下

Linux_第157张图片

将整个目录上传至/usr/local/nginx/html目录下

上传完成后,如图所示

Linux_第158张图片

执行解压缩命令

unzip html.zip

2). 修改Nginx配置文件nginx.conf

将nginx.conf配置文件中,将原有的监听80, 82, 8080端口号 的虚拟主机注释掉,引入如下的配置信息:

  upstream boot{
        # 200.1 宿主机
        server 192.168.200.138:8080;
        #server 192.168.200.129:8080;
  }
  server {
        listen       80;
        server_name  localhost;        location / {
            root   html;
            index  index.html;
        }
        # http://192.168.188.128/api/employee/login
        # 会被这个配置拦截住
        location ^~ /api/ {
            # 重定向的操作    
            # /employee/login
            rewrite ^/api/(.*)$ /$1 break;
            # http://192.168.200.138:8080/employee/login
            proxy_pass http://boot;
        }
        
        location = /50x.html {
            root   html;
        }
    }

3). 通过nginx访问前端工程

http://192.168.200.138/backend/page/login/login.html

4.4 反向代理配置

前端工程部署完成之后,我们可以正常的访问到系统的登录页面,点击登录按钮,可以看到服务端发起的请求,请求信息如下:

Linux_第159张图片

而大家知道,在我们之前开发的工程中,是没有/api这个前缀的,那这个时候,在不修改服务端代码的情况下,如何处理该请求呢?

实际上,通过nginx的就可以轻松解决这个问题。

在上述我们配置的nginx.conf中,除了配置了静态资源的加载目录以外,我们还配置了一段反向代理的配置,配置信息如下:

upstream boot{
        # 200.1 宿主机
        server 192.168.200.138:8080;
        #server 192.168.200.129:8080;
}location ^~ /api/ {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://boot;
}

这一段配置代表,如果请求当前nginx,并且请求的路径如果是 /api/ 开头,将会被该location处理。而在该location中,主要配置了两块儿信息: rewrite(url重写) 和 proxy_pass(反向代理)。 接下来我们就来解析一下这两项的配置。

1). 路径重写rewrite

rewrite ^/api/(.*)$ /$1 break;

这里写的是一个正则表达式,代表如果请求路径是以 /api/ 开头,后面的请求路径任意,此时将原始的url路径重写为 /$1,这里的$1指代的就是通配符 .* 这一块的内容。比如:

/api/employee/login ------> ^/api/(.*)$ --------> 此时 (.*) 匹配的就是 employee/login ------> 最终重写为/$1 : /employee/login

2). 反向代理

proxy_pass http://boot;

boot是一个虚拟名称的代表,代表是就是前面定义的upstream boot 。boot 代表是一个机器的集群。可以根据负载策略随机选择一台。如果仅有一台直接转发到这台主机。

路径重写后的请求,将会转发到后端的 http://192.168.200.138:8080 服务器中。

4.5 项目服务端部署

SpringBoot项目部署的核心思路与步骤:

  1. 环境安装:部署环境的安装

  2. 拉取代码:通过git命令,克隆并拉取仓库的代码,默认是master分支(发布时都用此分支)

  3. 编译打包:通过maven命令,对项目代码进行编译打包,输出jar包

  4. 启动项目:把输出的jar包复制到工作目录(运维人员指定的目录),并在后台启动。

  5. 测试后端接口:使用postman测试接口是否正常访问。

  6. 脚本部署与发布:如果经常修改项目,需要重新打包上线,建议直接使用脚本

1.环境安装

A. 确认JDK环境

B. 确认Git环境

C. 确认Maven环境

2.拉取代码

# 进入用户目录
cd ~
# 克隆代码 ,克隆后默认检查的master分支
git clone git@gitee.com:mobapp/reggie_take_out.git 
# 进入项目目录
cd ~/reggie_take_out
# 拉取代码(第1次克隆后,已经拉取过了,可以不执行)
git pull

如果克隆时出现如下提示:

Linux_第160张图片

说明需要把把当前服务器的SSH公钥放在gitee服务器上,才可以通过SSH协议拉取仓库的代码。

3.编译项目

1.进入仓库目录根目录,执行编译命令

# 进入项目目录
cd ~/reggie_take_out
mvn clean package -Dmaven.test.skip=true

正常编译如下:

Linux_第161张图片

备注:在执行mvn打包时,需要下载项目用的依赖仓库,如果网速很慢,这个过程会花费很长时间,如图所示:

Linux_第162张图片

建议ctrl+c强行终止,然后把本地的maven仓库或提供的mvn仓库,上传到服务器mvn默认仓库。

2.解压缩mvn仓库(编译失败,才执行此步骤)

mvn默认仓库是在用户目录下,以.m2开头

  • 把git仓库放在.m2下

cd ~/soft
# 解压到当前目录
unzip git仓库.zip
# 把解压的文件复制到 .m2下
cp -rf ./git仓库/*.* ~/.m2/

Linux_第163张图片

  • 解压缩上传的仓库,覆盖默认仓库

cd ~/.m2
unzip -o repository.zip

Linux_第164张图片

  • 再次执行编译指令

    cd ~/reggie_take_out
    mvn clean package -Dmaven.test.skip=true

    Linux_第165张图片

4.启动项目

  1. 启动之前先启动nginx、mysql、redis

备注:mysql数据库,需要安装reggie项目;redis暂时可以远程连接。

  • 启动nginx: /usr/local/nginx/sbin/nginx

  • 启动mysql(之前安装的mariadb): systemctl start mariadb

  • 在服务器上安装瑞吉项目库

Linux_第166张图片

  • 远程连接redis

    Linux_第167张图片

  1. 创建工作目录,把jar复制到工作目录

cd ~/
mkdir reggie_project
# reggie_take_out目录与自己的项目对应
# reggie_take_out-1.0-SNAPSHOT.jar文件 与自己的项目对应
\cp ~/reggie_take_out/target/reggie_take_out-1.0-SNAPSHOT.jar ~/reggie_project/
​
  1. 后台启动jar包

cd ~/reggie_project/
#reggie_take_out-1.0-SNAPSHOT.jar 与自己的项目名称对应
nohup java -jar reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &
# 查看启动日志
tail -f reggie_take_out.log

5.测试后端接口

测试登录

Linux_第168张图片

测试发送验证码(主要是测试Redis)

Linux_第169张图片

nohup java -jar -Dspring.profiles.active=pro reggie_take_out-1.0-SNAPSHOT.jar &> reggie_take_out.log &

6.脚本部署与发布

1.把脚本上传到工作目录

将资料中提供的start-reggie.sh和stop-reggie.sh文件上传到服务器工作目录

Linux_第170张图片

备注:.sh文件的将多个命令合并在一起的批处理命令。

2.设置脚本执行权限

cd ~/reggie_project/
chmod 755 *.sh

Linux_第171张图片

3) 执行start-reggie.sh脚本文件,自动部署项目

Linux_第172张图片

执行完shell脚本之后,我们可以通过 ps -ef|grep java 指令,查看服务是否启动。

查看启动日志

 tail -f reggie_take_out.log

4). 访问系统测试

http://192.168.200.138/backend/page/login/login.html

4.6 图片展示问题处理

在上述的测试中,我们发现菜品的图片无法正常展示。原因是因为,在我们的配置文件中,图片信息依然是从 D:/img 中加载的,但是在Linux服务器中,是不存在D盘的。

1). 修改文件存储目录,并提交代码

将文件存储目录修改为:

reggie:
  path: /usr/local/img/

2). 执行shell脚本,进行自动化部署

3).访问测试

http://192.168.200.138/backend/index.html

瑞吉外卖项目优化-Day02

课程内容

  • MySQL主从复制

  • 读写分离案例

  • 项目实现读写分离

  • Nginx-概述

  • Nginx-命令

  • Nginx-应用

前言

1). 存在的问题

在前面基础功能实现的过程中,我们后台管理系统及移动端的用户,在进行数据访问时,都是直接操作数据库MySQL的。结构如下图:

Linux_第173张图片

而在当前,MySQL服务器只有一台,那么就可能会存在如下问题:

1). 读和写所有压力都由一台数据库承担,压力大

2). 数据库服务器磁盘损坏则数据丢失,单点故障

2). 解决方案

为了解决上述提到的两个问题,我们可以准备两台MySQL,一台主(Master)服务器,一台从(Slave)服务器,主库的数据变更,需要同步到从库中(主从复制)。而用户在访问我们项目时,如果是写操作(insert、update、delete),则直接操作主库;如果是读(select)操作,则直接操作从库(在这种读写分离的结构中,从库是可以有多个的),这种结构我们称为 读写分离 。

Linux_第174张图片

今天我们就需要实现上述的架构,来解决业务开发中所存在的问题。

1. MySQL(Mariadb)主从复制

MySQL数据库默认是支持主从复制的,不需要借助于其他的技术,我们只需要在数据库中简单的配置即可。接下来,我们就从以下的几个方面,来介绍一下主从复制:

1.1 介绍

MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现 从库 的数据和 主库 的数据保持一致。MySQL主从复制是MySQL数据库自带功能,无需借助第三方工具。

二进制日志:

二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用,MySQL的主从复制, 就是通过该binlog实现的。默认MySQL是未开启该日志的。

MySQL的主从复制原理如下:

Linux_第175张图片

MySQL复制过程分成三步:

1). MySQL master 将数据变更写入二进制日志( binary log)

2). slave将master的binary log拷贝到它的中继日志(relay log)

3). slave重做中继日志中的事件,将数据变更反映它自己的数据

1.2 搭建

1.2.1 准备工作

提前准备两台服务器,并且在服务器中安装MySQL,服务器的信息如下:

数据库 IP 数据库版本
Master 192.168.200.200 5.7.25
Slave 192.168.200.201 5.7.25

并在两台服务器上做如下准备工作:

注意:如果已放开相应的端口号,就不需要再执行此操作了

1). 防火墙开放3306端口号

# 放开3306端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent
# 重新加载配置
firewall-cmd --reload
# 显示当前放开的端口号
firewall-cmd --zone=public --list-ports

2). 并将两台数据库服务器启动起来:

注意:此处根据自己安装的数据库启动

如果数据库已启动,就不需要再执行此操作了

启动Mariadb

systemctl start mariadb

启动MySQL

systemctl start mysqld

登录MySQL,验证是否正常启动

Linux_第176张图片

1.2.2 主库配置

服务器: 192.168.200.200

1). 修改Mysql数据库的配置文件/etc/my.cnf

在最下面增加配置:

log-bin=mysql-bin   #[必须]启用二进制日志
server-id=200       #[必须]服务器唯一ID(唯一即可)

Linux_第177张图片

2). 重启Mysql(Mariadb)服务

执行指令:

此处根据自己安装的数据库启动

重启Mariadb

systemctl restart mariadb

重启MySql

 systemctl restart mysqld

3). 创建数据同步的用户并授权

登录mysql

mysql -u root -p

并执行如下指令,创建用户并授权:

GRANT REPLICATION SLAVE ON *.* to 'xiaoming'@'%' identified by 'Root@123456';

注:上面SQL的作用是创建一个用户 xiaoming ,密码为 Root@123456 ,并且给xiaoming用户授予REPLICATION SLAVE权限。常用于建立复制时所需要用到的用户权限,也就是slave必须被master授权具有该权限的用户,才能通过该用户复制。

MySQL密码复杂程度说明:

Linux_第178张图片

目前mysql5.7默认密码校验策略等级为 MEDIUM , 该等级要求密码组成为: 数字、小写字母、大写字母 、特殊字符、长度至少8位

4). 登录Mysql数据库,查看master同步状态

执行下面SQL,记录下结果中FilePosition的值

show master status;

注:上面SQL的作用是查看Master的状态,执行完此SQL后不要再执行任何操作

1.2.3 从库配置

服务器: 192.168.200.201

1). 修改Mysql数据库的配置文件/etc/my.cnf

server-id=201 	#[必须]服务器唯一ID

Linux_第179张图片

2). 重启Mysql(Mariadb)服务

执行指令:

注意:此处根据自己安装的数据库启动

重启Mariadb

systemctl restart mariadb

重启MySql

 systemctl restart mysqld

3). 登录Mysql数据库,设置主库地址及同步位置

change master to master_host='192.168.188.128',master_user='xiaoming',master_password='Root@123456',master_log_file='mysql-bin.000001',master_log_pos=396;

start slave;

参数说明:

A. master_host : 主库的IP地址

B. master_user : 访问主库进行主从复制的用户名(上面在主库创建的)

C. master_password : 访问主库进行主从复制的用户名对应的密码

D. master_log_file : 从哪个日志文件开始同步(上述查询master状态中展示的有)

E. master_log_pos : 从指定日志文件的哪个位置开始同步(上述查询master状态中展示的有)

4). 查看从数据库的状态

show slave status;

然后通过状态信息中的 Slave_IO_running 和 Slave_SQL_running 可以看出主从同步是否就绪,如果这两个参数全为Yes,表示主从同步已经配置完成。

MySQL命令行技巧:

\G : 在MySQL的sql语句后加上\G,表示将查询结果进行按列打印,可以使每个字段打印到单独的行。即将查到的结构旋转90度变成纵向;

1.3 测试

主从复制的环境,已经搭建好了,接下来,我们可以通过Navicat连接上两台MySQL服务器,进行测试。测试时,我们只需要在主库Master执行操作,查看从库Slave中是否将数据同步过去即可。

1). 在master中创建数据库itcast, 刷新slave查看是否可以同步过去

Linux_第180张图片

2). 在master的itcast数据下创建user表, 刷新slave查看是否可以同步过去

Linux_第181张图片

3). 在master的user表中插入一条数据, 刷新slave查看是否可以同步过去

Linux_第182张图片

2. 读写分离案例

2.1 背景介绍

面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

Linux_第183张图片

通过读写分离,就可以降低单台数据库的访问压力, 提高访问效率,也可以避免单机故障。

主从复制的结构,我们在第一节已经完成了,那么我们在项目中,如何通过java代码来完成读写分离呢,如何在执行select的时候查询从库,而在执行insert、update、delete的时候,操作主库呢?这个时候,我们就需要介绍一个新的技术 ShardingJDBC。

2.2 ShardingJDBC介绍

Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

使用Sharding-JDBC可以在程序中轻松的实现数据库读写分离。

Sharding-JDBC具有以下几个特点:

1). 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。

2). 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。

3). 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。

依赖:


    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0-RC1

2.3 数据库环境

在主库中创建一个数据库rw, 并且创建一张表, 该数据库及表结构创建完毕后会自动同步至从数据库,SQL语句如下:

create database rw default charset utf8mb4;

use rw;

CREATE TABLE `user` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO user (name, age, address) VALUES ('张三', 100, '昌平');
INSERT INTO user (name, age, address) VALUES ('李四', 0, '顺义');
INSERT INTO user (name, age, address) VALUES ('星越L', 21, '北京');

Linux_第184张图片

2.4 初始工程导入

我们本案例主要是演示一下读写分离操作,对于基本的增删改查的业务操作,我们就不再去编写了,我们可以直接导入资料中提供的demo工程(rw_demo),在demo工程中,我们已经完成了user的增删改查操作,具体的工程结构如下:

Linux_第185张图片

2.5 读写分离配置

1). 在pom.xml中增加shardingJdbc的maven坐标


    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0-RC1

2). 在application.yml中增加配置

spring:
  main:
    # 如果当前项目中存在同名的bean,后定义的bean会覆盖先定义的
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      names:
        master,slave
      # 主数据源
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.200:3306/rw?characterEncoding=utf-8
        username: root
        password: root
      # 从数据源
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.201:3306/rw?characterEncoding=utf-8
        username: root
        password: root
    masterslave:
      # 读写分离配置
      load-balance-algorithm-type: round_robin #轮询
      # 最终的数据源名称
      name: dataSource
      # 主库数据源名称
      master-data-source-name: master
      # 从库数据源名称列表,多个逗号分隔
      slave-data-source-names: slave
    props:
      sql:
        show: true #开启SQL显示,默认false

配置解析:

Linux_第186张图片

如果不配置该项,项目启动之后将会报错:

报错信息表明,在声明 org.apache.shardingsphere.shardingjdbc.spring.boot 包下的SpringBootConfiguration中的dataSource这个bean时出错, 原因是有一个同名的 dataSource 的bean在com.alibaba.druid.spring.boot.autoconfigure包下的DruidDataSourceAutoConfigure类加载时已经声明了。

Linux_第187张图片

Linux_第188张图片

而我们需要用到的是 shardingjdbc包下的dataSource,所以我们需要配置上述属性,让后加载的覆盖先加载的。

2.6 测试

我们使用shardingjdbc来实现读写分离,直接通过上述简单的配置就可以了。配置完毕之后,我们就可以重启服务,通过postman来访问controller的方法,来完成用户信息的增删改查,我们可以通过debug及日志的方式来查看每一次执行增删改查操作,使用的是哪个数据源,连接的是哪个数据库。

1). 保存数据

Linux_第189张图片

控制台输出日志,可以看到操作master主库:

2). 修改数据

Linux_第190张图片

控制台输出日志,可以看到操作master主库:

3). 查询数据

Linux_第191张图片

控制台输出日志,可以看到操作slave主库:

4). 删除数据

Linux_第192张图片

控制台输出日志,可以看到操作master主库:

3. 项目实现读写分离

3.1 数据库环境准备

直接使用我们前面在虚拟机中搭建的主从复制的数据库环境即可。在主库中创建瑞吉外卖项目的业务数据库reggie, 并导入相关表结构和数据(我们可以将自己之前在本地开发时使用的数据库数据导出, 然后导入到服务器中的主库即可)。

1). 将自己本地的reggie数据库的数据导出SQL文件

Linux_第193张图片

这样做的话,我们之前自己开发时,添加的测试数据都还在的,便于测试。

2). 在主数据库master中,创建数据库reggie,并导入该SQL文件

master中创建数据库,会自动同步至slave从库

Linux_第194张图片

在master的reggie中导入sql文件

Linux_第195张图片

3.2 创建Git分支

目前默认git中有两个分支master 和 v1.0 ,我们接下来进行读写分离的优化,就不在master和v1.0分支来操作了,我们需要在git上创建一个单独的分支v1.1,读写分离的优化,我们就在该分支上进行操作。具体创建分支的操作,和前面演示的一致。

当前创建的v1.1分支,是基于master分支创建出来的,所以目前master分支的代码, 和v1.1分支的代码是完全一样的,接下来把v1.1的代码也推送至远程仓库。

3.3 读写分离配置

1). 在项目的pom.xml增加依赖


    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0-RC1

2). 在项目的application.yml中配置数据源相关信息

spring:
  main:
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      names:
        master,slave
      # 主数据源
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.200:3306/reggie?characterEncoding=utf-8
        username: root
        password: root
      # 从数据源
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.200.201:3306/reggie?characterEncoding=utf-8
        username: root
        password: root
    masterslave:
      # 读写分离配置
      load-balance-algorithm-type: round_robin #轮询
      # 最终的数据源名称
      name: dataSource
      # 主库数据源名称
      master-data-source-name: master
      # 从库数据源名称列表,多个逗号分隔
      slave-data-source-names: slave
    props:
      sql:
        show: true #开启SQL显示,默认false

3.4 功能测试

配置完毕之后,我们启动项目进行测试,直接访问系统管理后台的页面,然后执行相关业务操作,看控制台输出的日志信息即可。

查询操作:

更新操作:

插入操作:

删除操作:

3.5 Git合并代码

读写分离的功能我们已经实现完毕了,那么接下来,我们就可以将当前分支v1.1代码提交并推送到远程仓库。

Linux_第196张图片

Linux_第197张图片

然后,再将v1.1的代码,合并到master分支,然后推送至远程仓库。

Linux_第198张图片

4. Nginx-概述

4.1 介绍

Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx的网站有:百度、京东、新浪、网易、腾讯、淘宝等。

Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。

官网:nginx news

4.2 下载和安装

4.2.1 下载

在Nginx的官网的下载页面中(nginx: download),就展示了当前Nginx版本,并提供了下载的连接。 如下:

Linux_第199张图片

在本项目中,我们所学习的Nginx选择的是稳定版本的1.16这个版本,我们可以直接从官网下载,当然在我们的课程资料中也已经提供了该版本的安装包。

4.2.2 安装

1). 安装依赖包

由于nginx是基于c语言开发的,所以需要安装c语言的编译环境,及正则表达式库等第三方依赖库。

yum -y install gcc pcre-devel zlib-devel openssl openssl-devel

2). 下载Nginx安装包

yum install wget
wget https://nginx.org/download/nginx-1.16.1.tar.gz

wget :

wget命令用来从指定的URL下载文件。wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。

执行完wget指令后,就会在当前所在目录看到下载下来的文件。

3). 解压nginx压缩包

tar -zxvf nginx-1.16.1.tar.gz

4). 配置Nginx编译环境

cd nginx-1.16.1
./configure --prefix=/usr/local/nginx

说明:

--prefix 指定的目录,就是我们安装Nginx的目录。

5). 编译&安装

make & make install

4.3 目录结构

安装完Nginx后,我们可以切换到Nginx的安装目录(/usr/local/nginx),先来熟悉一下Nginx的目录结构,如下图:

Linux_第200张图片

备注:

上述我们用到的一个指令 tree,该指令可以将我们指定的目录以树状结构展示出来。如果没有这个指令,可以通过以下指令进行安装。

yum install tree

重点目录和文件如下:

目录/文件 说明 备注
conf 配置文件的存放目录
conf/nginx.conf Nginx的核心配置文件 conf下有很多nginx的配置文件,我们主要操作这个核心配置文件
html 存放静态资源(html, css, ) 部署到Nginx的静态资源都可以放在html目录中
logs 存放nginx日志(访问日志、错误日志等)
sbin/nginx 二进制文件,用于启动、停止Nginx服务

5. Nginx-命令

5.1 常用命令

Nginx中,我们的二进制可执行文件(nginx)存放在sbin目录下,虽然只有一个可执行文件,但是我们可以通过该指令配合不同的参数达到更加强大的功能。接下来,我们就演示一下Nginx常见指令, 在执行下面的指令时,都需要在/usr/local/nginx/sbin/目录下执行。

1). 查看版本

./nginx -v

2). 检查配置文件

修改了nginx.conf核心配置文件之后,在启动Nginx服务之前,可以先检查一下conf/nginx.conf文件配置的是否有错误,命令如下:

./nginx -t

3). 启动

./nginx

启动之后,我们可以通过ps -ef指令来查看nginx的进程是否存在。

注意: nginx服务启动后,默认就会有两个进程。

启动之后,我们可以直接访问Nginx的80端口, http://192.168.200.200

Linux_第201张图片

注意:

要想正常访问Nginx,需要关闭防火墙或开放指定端口号,执行的指令如下:

A. 关闭防火墙

systemctl stop firewalld

B. 开放80端口

firewall-cmd --zone=public --add-port=80/tcp --permanent

firewall-cmd --reload

4). 停止

./nginx -s stop

停止之后,我们可以查看nginx的进程:

ps -ef|grep nginx

5). 重新加载

当修改了Nginx配置文件后,需要重新加载才能生效,可以使用下面命令重新加载配置文件:

./nginx -s reload

6. Nginx-应用

介绍了并安装了Nginx之后,本章节将要讲解的是Nginx的使用,我们主要从以下四个方面进行讲解。

6.1 配置文件结构

nginx的配置文件(conf/nginx.conf)整体上分为三部分: 全局块、events块、http块。这三块的分别配置什么样的信息呢,看下表:

区域 职责
全局块 配置和nginx运行相关的全局配置
events块 配置和网络连接相关的配置
http块 配置代理、缓存、日志记录、虚拟主机等配置

具体结构图如下:

Linux_第202张图片

在全局块、events块以及http块中,我们经常配置的是http块。

在http块中可以包含多个server块,每个server块可以配置多个location块。

6.2 部署静态资源

6.2.1 介绍

Nginx可以作为静态web服务器来部署静态资源。这里所说的静态资源是指在服务端真实存在,并且能够直接展示的一些文件,比如常见的html页面、css文件、js文件、图片、视频等资源。

相对于Tomcat,Nginx处理静态资源的能力更加高效,所以在生产环境下,一般都会将静态资源部署到Nginx中。

将静态资源部署到Nginx非常简单,只需要将文件复制到Nginx安装目录下的html目录中即可。

server {
    listen 80;              #监听端口   
    server_name localhost;  #服务器名称
    location / {            #匹配客户端请求url
        root html;          #指定静态资源根目录
        index index.html;   #指定默认首页
    }
}

6.2.2 测试

在资料中,我们提供了一个静态的html文件,我们需要将这个文件部署到nginx中,然后通过nginx访问html静态资源。

1). 将静态资源上传到 /usr/local/nginx/html 目录

2). 启动nginx

Linux_第203张图片

3). 访问

http://192.168.200.200/hello.html

Linux_第204张图片

http://192.168.200.200 , 访问该地址,访问的是nginx的默认首页

Linux_第205张图片

4). 配置首页

Linux_第206张图片

如果我们需要将hello.html作为nginx的首页,可以修改location的index指令,配置为hello.html,如下:

Linux_第207张图片

配置完毕后,我们可以通过指令,来检查配置文件是否配置正确: nginx -t

配置文件修改了,我们需要重新加载一下,才可以生效:

nginx -s reload

5). 访问

http://192.168.200.200

Linux_第208张图片

6.3 反向代理

6.3.1 概念介绍

1). 正向代理

正向代理服务器是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。

正向代理一般是在客户端设置代理服务器,通过代理服务器转发请求,最终访问到目标服务器。

Linux_第209张图片

2). 反向代理

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源,反向代理服务器负责将请求转发给目标服务器。用户不需要知道目标服务器的地址,也无须在用户端作任何设定,对于用户来说,访问反向代理服务器是完全无感知的。

Linux_第210张图片

那么在本小节,我们就是要使用nginx来作为反向代理服务器使用。 在nginx中,我们可以在nginx.conf中配置反向代理:

server {
    listen 82;
    server_name localhost;
    location / {
        proxy_pass http://192.168.200.201:8080;     #反向代理配置,将请求转发到指定服务
    }
}

上述配置的含义为: 当我们访问nginx的82端口时,根据反向代理配置,会将请求转发到 http://192.168.200.201:8080 对应的服务上。

6.3.2 测试

需求: 在192.168.200.201这台服务器中部署了java应用,运行端口为8080,并提供了一个可访问的链接 /hello。现在我们需要在访问nginx的82端口时,通过nginx将请求转发到192.168.200.201:8080的服务。

Linux_第211张图片

1). 在192.168.200.201部署服务并启动

将资料中提供的 helloworld-1.0-SNAPSHOT.jar 上传到服务器端,并通过指令 java -jar helloworld-1.0-SNAPSHOT.jar 运行服务。

2). 在192.168.200.200中的nginx.conf中配置反向代理

进入nginx的安装目录,并编辑配置文件nginx.conf:

cd /usr/local/nginx/conf/
vim nginx.conf

在http块中,再添加一个server块虚拟主机的配置,监听82端口,并配置反向代理proxy_pass:

server {
    listen 82;
    server_name localhost;
    location / {
        proxy_pass http://192.168.200.201:8080;     #反向代理配置,将请求转发到指定服务
    }
}

3). 检查配置文件,并重新加载

nginx -t

nginx -s reload

4). 访问

注意: 在访问82端口时,有可能访问不通,原因是以为防火墙中没有开放端口号。我们可以通过两种方式来解决该问题:

A. 关闭防火墙

systemctl stop firewalld

B. 开发指定端口

firewall-cmd --zone=public --add-port=82/tcp --permanent
​
firewall-cmd --reload

6.4 负载均衡

6.4.1 概念介绍

早期的网站流量和业务功能都比较简单,单台服务器就可以满足基本需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器组成应用集群,进行性能的水平扩展以及避免单点故障出现。

应用集群:将同一应用部署到多台机器上,组成应用集群,接收负载均衡器分发的请求,进行业务处理并返回响应数据

负载均衡器:将用户请求根据对应的负载均衡算法分发到应用集群中的一台服务器进行处理

Linux_第212张图片

此处的负载均衡器,我们将会使用Nginx来实现,而Nginx的负载均衡是基于反向代理的,只不过此时所代理的服务器不是一台,而是多台。

6.4.2 测试

1). 将资料中提供的两个jar包,上传到192.168.200.201服务器上

jar 运行端口 请求链接 响应数据
8080 /hello 8080
8081 /hello 8081

我们在测试时,并没有那么多服务器,我们可以在一台服务器中启动多个服务,运行在不同的端口号上进行测试。

2). 运行上传上来的两个jar包,运行端口分别是 8080 , 8081

由于我们执行 java -jar 指令会占用前台窗口,所以我们可以开启两个窗口进行测试。

3). 在nginx中配置负载均衡

打开nginx的配置文件nginx.conf并增加如下配置:

#upstream指令可以定义一组服务器
upstream targetserver{  
    server 192.168.200.201:8080;
    server 192.168.200.201:8081;
}server {
    listen       8888;
    server_name  localhost;
    location / {
        proxy_pass http://targetserver;
    }
}

具体的配置位置如下:

Linux_第213张图片

4). 重新加载nginx配置文件,访问

nginx -s reload

测试时,我们直接访问nginx的8080端口(http://192.168.200.200:8080), 此时nginx会根据负载均衡策略,将请求转发到后面的两台服务器。

Linux_第214张图片

在上述的测试过程中,我们看到请求均衡的转发到了8080和8081,因为模式的负载均衡策略是轮询。

注意: 上述所有涉及到的端口号,都需要在对应的服务器的防火墙中开放,或者彻底关闭防火墙

6.4.3 负载均衡策略

处理上述默认的轮询策略以外,在Nginx中还提供了其他的负载均衡策略,如下:

名称 说明 特点
轮询 默认方式
weight 权重方式 根据权重分发请求,权重大的分配到请求的概率大
ip_hash 依据ip分配方式 根据客户端请求的IP地址计算hash值, 根据hash值来分发请求, 同一个IP发起的请求, 会发转发到同一个服务器上
least_conn 依据最少连接方式 哪个服务器当前处理的连接少, 请求优先转发到这台服务器
url_hash 依据url分配方式 根据客户端请求url的hash值,来分发请求, 同一个url请求, 会发转发到同一个服务器上
fair 依据响应时间方式 优先把请求分发给处理请求时间短的服务器

权重的配置:

#upstream指令可以定义一组服务器
upstream targetserver{  
    server 192.168.200.201:8080 weight=10;
    server 192.168.200.201:8081 weight=5;
}

上述配置的weight权重是相对的,在上述的配置中,效果就是,在大数据量的请求下,最终8080接收的请求数是8081的两倍。

【附录】

1.安装mysql(mariadb)【yum】

MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB

1)查看CentOS自带的mysql

输入 rpm -qa | grep mysql

2)将自带的mysql卸载

rpm -e --nodeps

3)yum安装

yum -y install mariadb-server

4)启动mysql

systemctl start mariadb

5)设置root密码

注:这只是设置root用户在本机(linux)登录时的密码

mysqladmin -u root password 'root'  

6)进入mysql

mysql -u root -p

备注:输入密码:root

进入到数据库的执行命令行里面了。

7)  进入mysql,并执行下面sql

保证密码和本地一致

下面的话在mysql数据库里面里面执行

  -- 查看当前的数据库
show databases;
  -- 打开mysql
use mysql ;
  -- 查看所有表
show tables;
​
  -- 我们不用ipv6的地址,直接把host改为%,表示所有客户端都可以连接;同时设置密码为root
update user set host='%' ,password=password("root") where user='root' and host = '::1' ;
  -- 刷新后才能生效
flush privileges;

退出数据库命令操作

exit;
  1. 开放端口号 (Linux命令)

# 开放端口命令
firewall-cmd --zone=public --add-port=3306/tcp --permanent
#重新加载配置
firewall-cmd --reload

2.Nginx环境变量配置

在上述我们在使用nginx命令在进行服务的启动、停止、重新加载时,都需要用到一个指令nginx,而这个指令是在nginx/sbin目录下的,我们每一次使用这个指令都需要切换到sbin目录才可以,使用相对繁琐。那么我们能不能在任意目录下都可以执行该指令来操作nginx呢?答案是可以的,配置nginx的环境变量即可。

通过vim编辑器,打开/etc/profile文件, 在PATH环境变量中增加nginx的sbin目录,如下:

修改完配置文件之后,需要执行 source /etc/profile 使文件生效。 接下来,我们就可以在任意目录下执行nginx的指令了,如:

6.2.2 测试

在资料中,我们提供了一个静态的html文件,我们需要将这个文件部署到nginx中,然后通过nginx访问htmLl静态资源。

1). 将静态资源上传到 /usr/local/nginx/html 目录

2). 启动nginx

Linux_第215张图片

3). 访问

http://192.168.200.200/hello.html

Linux_第216张图片

http://192.168.200.200 , 访问该地址,访问的是nginx的默认首页

Linux_第217张图片

4). 配置首页

Linux_第218张图片

如果我们需要将hello.html作为nginx的首页,可以修改location的index指令,配置为hello.html,如下:

Linux_第219张图片

配置完毕后,我们可以通过指令,来检查配置文件是否配置正确: nginx -t

配置文件修改了,我们需要重新加载一下,才可以生效:

nginx -s reload

5). 访问

http://192.168.200.200

Linux_第220张图片

6.3 反向代理

6.3.1 概念介绍

1). 正向代理

正向代理服务器是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。

正向代理一般是在客户端设置代理服务器,通过代理服务器转发请求,最终访问到目标服务器。

Linux_第221张图片

2). 反向代理

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源,反向代理服务器负责将请求转发给目标服务器。用户不需要知道目标服务器的地址,也无须在用户端作任何设定,对于用户来说,访问反向代理服务器是完全无感知的。

Linux_第222张图片

那么在本小节,我们就是要使用nginx来作为反向代理服务器使用。 在nginx中,我们可以在nginx.conf中配置反向代理:

server {
    listen 82;
    server_name localhost;
    location / {
        proxy_pass http://192.168.200.201:8080;     #反向代理配置,将请求转发到指定服务
    }
}

上述配置的含义为: 当我们访问nginx的82端口时,根据反向代理配置,会将请求转发到 http://192.168.200.201:8080 对应的服务上。

6.3.2 测试

需求: 在192.168.200.201这台服务器中部署了java应用,运行端口为8080,并提供了一个可访问的链接 /hello。现在我们需要在访问nginx的82端口时,通过nginx将请求转发到192.168.200.201:8080的服务。

Linux_第223张图片

1). 在192.168.200.201部署服务并启动

将资料中提供的 helloworld-1.0-SNAPSHOT.jar 上传到服务器端,并通过指令 java -jar helloworld-1.0-SNAPSHOT.jar 运行服务。

2). 在192.168.200.200中的nginx.conf中配置反向代理

进入nginx的安装目录,并编辑配置文件nginx.conf:

cd /usr/local/nginx/conf/
vim nginx.conf

在http块中,再添加一个server块虚拟主机的配置,监听82端口,并配置反向代理proxy_pass:

server {
    listen 82;
    server_name localhost;
    location / {
        proxy_pass http://192.168.200.201:8080;     #反向代理配置,将请求转发到指定服务
    }
}

3). 检查配置文件,并重新加载

nginx -t

nginx -s reload

4). 访问

注意: 在访问82端口时,有可能访问不通,原因是以为防火墙中没有开放端口号。我们可以通过两种方式来解决该问题:

A. 关闭防火墙

systemctl stop firewalld

B. 开发指定端口

firewall-cmd --zone=public --add-port=82/tcp --permanent
​
firewall-cmd --reload

6.4 负载均衡

6.4.1 概念介绍

早期的网站流量和业务功能都比较简单,单台服务器就可以满足基本需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器组成应用集群,进行性能的水平扩展以及避免单点故障出现。

应用集群:将同一应用部署到多台机器上,组成应用集群,接收负载均衡器分发的请求,进行业务处理并返回响应数据

负载均衡器:将用户请求根据对应的负载均衡算法分发到应用集群中的一台服务器进行处理

Linux_第224张图片

此处的负载均衡器,我们将会使用Nginx来实现,而Nginx的负载均衡是基于反向代理的,只不过此时所代理的服务器不是一台,而是多台。

6.4.2 测试

1). 将资料中提供的两个jar包,上传到192.168.200.201服务器上

jar 运行端口 请求链接 响应数据
8080 /hello 8080
8081 /hello 8081

我们在测试时,并没有那么多服务器,我们可以在一台服务器中启动多个服务,运行在不同的端口号上进行测试。

2). 运行上传上来的两个jar包,运行端口分别是 8080 , 8081

由于我们执行 java -jar 指令会占用前台窗口,所以我们可以开启两个窗口进行测试。

3). 在nginx中配置负载均衡

打开nginx的配置文件nginx.conf并增加如下配置:

#upstream指令可以定义一组服务器
upstream targetserver{  
    server 192.168.200.201:8080;
    server 192.168.200.201:8081;
}server {
    listen       8888;
    server_name  localhost;
    location / {
        proxy_pass http://targetserver;
    }
}

具体的配置位置如下:

Linux_第225张图片

4). 重新加载nginx配置文件,访问

nginx -s reload

测试时,我们直接访问nginx的8080端口(http://192.168.200.200:8080), 此时nginx会根据负载均衡策略,将请求转发到后面的两台服务器。

Linux_第226张图片

在上述的测试过程中,我们看到请求均衡的转发到了8080和8081,因为模式的负载均衡策略是轮询。

注意: 上述所有涉及到的端口号,都需要在对应的服务器的防火墙中开放,或者彻底关闭防火墙

6.4.3 负载均衡策略

处理上述默认的轮询策略以外,在Nginx中还提供了其他的负载均衡策略,如下:

名称 说明 特点
轮询 默认方式
weight 权重方式 根据权重分发请求,权重大的分配到请求的概率大
ip_hash 依据ip分配方式 根据客户端请求的IP地址计算hash值, 根据hash值来分发请求, 同一个IP发起的请求, 会发转发到同一个服务器上
least_conn 依据最少连接方式 哪个服务器当前处理的连接少, 请求优先转发到这台服务器
url_hash 依据url分配方式 根据客户端请求url的hash值,来分发请求, 同一个url请求, 会发转发到同一个服务器上
fair 依据响应时间方式 优先把请求分发给处理请求时间短的服务器

权重的配置:

#upstream指令可以定义一组服务器
upstream targetserver{  
    server 192.168.200.201:8080 weight=10;
    server 192.168.200.201:8081 weight=5;
}

上述配置的weight权重是相对的,在上述的配置中,效果就是,在大数据量的请求下,最终8080接收的请求数是8081的两倍。

【附录】

1.安装mysql(mariadb)【yum】

MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB

1)查看CentOS自带的mysql

输入 rpm -qa | grep mysql

2)将自带的mysql卸载

rpm -e --nodeps

3)yum安装

yum -y install mariadb-server

4)启动mysql

systemctl start mariadb

5)设置root密码

注:这只是设置root用户在本机(linux)登录时的密码

mysqladmin -u root password 'root'  

6)进入mysql

mysql -u root -p

备注:输入密码:root

进入到数据库的执行命令行里面了。

7)  进入mysql,并执行下面sql

保证密码和本地一致

下面的话在mysql数据库里面里面执行

  -- 查看当前的数据库
show databases;
  -- 打开mysql
use mysql ;
  -- 查看所有表
show tables;
​
  -- 我们不用ipv6的地址,直接把host改为%,表示所有客户端都可以连接;同时设置密码为root
update user set host='%' ,password=password("root") where user='root' and host = '::1' ;
  -- 刷新后才能生效
flush privileges;

退出数据库命令操作

exit;
  1. 开放端口号 (Linux命令)

# 开放端口命令
firewall-cmd --zone=public --add-port=3306/tcp --permanent
#重新加载配置
firewall-cmd --reload

2.Nginx环境变量配置

在上述我们在使用nginx命令在进行服务的启动、停止、重新加载时,都需要用到一个指令nginx,而这个指令是在nginx/sbin目录下的,我们每一次使用这个指令都需要切换到sbin目录才可以,使用相对繁琐。那么我们能不能在任意目录下都可以执行该指令来操作nginx呢?答案是可以的,配置nginx的环境变量即可。

通过vim编辑器,打开/etc/profile文件, 在PATH环境变量中增加nginx的sbin目录,如下:

修改完配置文件之后,需要执行 source /etc/profile 使文件生效。 接下来,我们就可以在任意目录下执行nginx的指令了,如:

你可能感兴趣的:(java)