应用部署优化方案分享

白昼怎懂夜的黑 提交于 2020-01-07 04:12:36

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

转载本文需注明出处:微信公众号EAWorld,违者必究。

 

引言:

 

在企业级应用实施和运营过程中,为了解决企业中部分业务场景访问量大、并发量高的问题,就需要对系统架构及应用参数做出优化和调整,如架构优化、数据库优化、应用优化等。

应用系统部署优化是一个不断尝试、实践、总结的过程,并针对不同企业的特点制定相关解决方案。通过应用系统架构、数据库及应用优化入手,并通过相关案例加以说明和解释。

 

目录:

 

1、应用系统架构简介

2、数据库及应用优化方案

3、优化案例分析

 

1. 应用系统架构简介

 

应用系统架构的发展

 

当今互联网技术发展日新月异,应用系统架构也在不断的更新迭代,从传统的单一架构演变为如今的集群架构、分布式、微服务架构等,以便满足用户对系统的要求。

 

NO1.单机部署架构

 

互联网建设初期,用户访问量有限,数据量不大,多数系统采用单台服务器部署应用服务,系统服务、文件、数据库等所有系统资源部署在一台服务器上.

 

 

NO2.应用和数据分离

 

随着用户量和数据量的不断攀升,业务对系统的性能要求越来越高,这是需要将应用和数据分离,单独部署相关的业务组件。

 

 

NO3.引入NoSQL数据库架构

 

随着用户不断的增加,关系型数据库压力变大,访问延迟,性能下降,这时加入缓存技术,将查询较多数据缓存起来,以加快应用访问速度。

 

 

NO4.应用集群部署

 

在访问量高峰时期,单一的系统服务往往无法承受巨大的访问量,这时就需要做集群服务,以减少单台服务器的压力。

 

 

中小企业应用系统多数为集群部署,既保证系统的稳定性,又能降低因服务器故障,造成数据丢失的风险。

 

其他在应用集群部署方案上演变的架构系统,如:分布式、微服务架构等,对系统稳定性和安全性做的更加出色。

 

2.数据库及应用优化方案

 

本章节主要介绍mysql数据库的部署及常见优化方案;应用以tomcat为例,简单介绍tomcat的常见参数优化配置。

 

  • 数据库分类介绍

 

当今的互联网企业中,最常用的数据库模式主要有两种,即关系型数据库和非关系型数据库。

 

关系型数据库:采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,行和列被称为表,一组表组成了数据库。

 

  • MySQL:甲骨文旗下产品,体积小、速度快、成本低,代码开源,适用于中小型网站开发

  • ORACLE:同样为甲骨文旗下产品,Oracle可移植性好、使用方便、功能强,高效率、可靠性好的、适应高吞吐量的数据库方案

  • SQLServer:微软旗下产品,图像化用户界面,使用方便、web技术支持良好、丰富的编程接口

 

非关系型数据库:去掉关系数据库的关系型特性,数据之间无关系,非常容易扩展。同时也在架构的层面上带来了可扩展能力。大数据量,高性能,NoSQL数据库具有非常高的读写性能。

 

  • Redis:基于内存亦可持久化的日志型、Key-Value数据库

  • MongoDB:分布式文件存储数据库,高效的二进制数据存储,使用方便

  • HBASE:列存储数据库,以列簇式存储,将同一列数据存在一起

 

  • MySQL数据库部署

 

案例系统环境为RadHat_6.6_64;数据库版本为MySQL-5.7.23社区版(mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar)。

 

mysql安装方法有RPM包安装和源码包安装,RPM安装是最简单的安装方法,不需要源码编译适合初学者安装使用。

 

1.检查系统是否含有自带mysql  

使用命令# rpm -qa|grep -i mysql

 

2.yum卸载自带mysql

使用命令# yum -y remove mysql-libs-*

卸载完成后,请再次执行步骤1进行检查

 

3.上传mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar到服务器,并解压缩

# tar –xvf mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar

 

4.rpm安装mysql数据库,按照顺序以下命令执行

#rpm -ivh mysql-community-common-5.7.23-1.el6.x86_64.rpm

#rpm -ivh mysql-community-libs-5.7.23-1.el6.x86_64.rpm

#rpm -ivh mysql-community-libs-compat-5.7.23-1.el6.x86_64.rpm

#rpm -ivh mysql-community-embedded-5.7.23-1.el6.x86_64.rpm   

#rpm -ivh mysql-community-devel-5.7.23-1.el6.x86_64.rpm

#rpm -ivh mysql-community-embedded-devel-5.7.23-1.el6.x86_64.rpm

#rpm -ivh mysql-community-client-5.7.23-1.el6.x86_64.rpm

#rpm -ivh mysql-community-server-5.7.23-1.el6.x86_64.rpm

 

5.初始化数据库

# mysqld --initialize 

 

6.启动数据库并修改root默认密码

使用命令 # service mysqld start      --启动数据库

使用命令 # service mysqld status    --检查数据库状态

使用命令 # cat /var/log/mysqld.log   --查看数据库root初始化密码

登录mysql数据库:

# mysql -uroot –p ‘!w1wzCxJprmv’

设置root用户的新密码:

#set password=password('******');

 

可设置mysql服务开机自启动:

chkconfig --add mysqld

chkconfig mysqld on

检查:chkconfig --list mysqld

 

MySQL参数优化

 

需要修改my.cnf配置文件,修改完成后,重新启动mysql   # service mysqld restart

 

参数设置:

 

  • skip-name-resolve    

#开启该选项,则所有远程主机连接授权都要使用IP地址方式

 

  • back_log = 512        

#系统在一个短时间内有很多连接,则需要增大该值,该值指定到来的TCP/IP连接的侦听队列的大小,Linux系统推荐设置为小于512的整数

 

  • max_allowed_packet = 4M    

#限制插入的数据包大小

 

  • max_connections = 500      

#指定MySQL允许的最大连接进程数

 

  • sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER

# NO_ENGIN_SUBSTITUTION 在创建表指定一个不存在的存储引擎,mysql会提示错误,反之,则会设置成默认的innodb

# STRICT_TRANS_TABLES 在插入或更新数据时进行更严格的检查,如果发现某个值缺失或非法,MySQL将抛出错误,语句会停止运行并回滚

# NO_AUTO_CREATE_USER 新建用户不能空密码

lower_case_table_names=1                   

#“0”是表名存储是给定的大小写,比较是区分大小写的      “1”表名存储在磁盘是小写,比较是不区分大小写的    “2”表名存储是给定的大小写,比较是小写

 

  • explicit_defaults_for_timestamp=true       

#如果一行数据中某些列被更新了,如果这一行中有timestamp类型的列,那么这个timestamp列的数据也会被自动更新到,更新操作所发生的那个时间点

skip-networking        

#开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果WEB服务器是以远程连接的方式访问MySQL数据库服务器则不要开启该选项!!!!!

 

MySQL不同访问量级时的架构应用

 

日访问量为万级以内

无需做架构层优化,应用和数据库分离部署,但是考虑数据的安全和备份,可以考虑搭建主从部署,主数据库承担所有业务访问,从数据库用作热备

 

日访问量达到十万以上

可以考虑一主多从(读写分离)架构,即主数据库承担“写”任务,从数据库承担“读”任务

 

日访问量达到百万以上

一主已经无法承担相关业务访问,需要进一步作出调整。我们将相关的用户、业务、权限等分离出来,单独运行至一个数据库,然后再做主从,即分库;也可以将读取量或者写入量大的表分离出来,单独运行至一个数据库,或者将大表分离成多个小表,即分表。这种方式就是分库分表的模式

 

  • 主从同步架构介绍

 

 

可用于用户量较小,允许短时终止服务的子系统或小型系统。

 

当master出现故障时,可以通过手动调整web应用服务器连接数据库的地址,将数据库请求切换到slave数据库中。

 

当master故障修复后,可以将slave数据库的整个mysql-data目录拷贝至master中,值得注意的是,mysql-data目录中包含auto.cnf文件,这是mysql的server-uuid值,需要继续使用master中原有的值,然后重新配置主从同步。

 

[auto]

server-uuid=a34c331b-e55c-11e9-9107-000c292efb70

 

也可以将Slave用作主库使用,Master当作从库使用,重新配置主从同步。

 

主从同步部署

 

1.主库创建同步用户

mysql>GRANT REPLICATION SLAVE,FILE ON *.* TO 'replication'@'%' IDENTIFIED BY '*******'

 

2.修改主库配置文件

编辑my.cnf文件

log-bin=mysql-bin         #日志文件名

server-id=1              #主数据库端ID号

修改问完成,请重启

 

3.查询主库master状态

mysql> show master status;

+------------------+----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000001 | 154 | | |

+------------------+----------+--------------+------------------+

调整完毕后不要再操作主库,防止主库数据发生变化

 

4.从库执行同步命令

mysql>change master to master_host=‘192.168.0.1’,master_user= ‘replication ’,master_password=‘******',master_log_file='mysql-bin.000001',master_log_pos=154;

mysql>start slave;    #开启同步 

 

5.检查从库同步状态

show slave status\G;   

# Slave_IO_Running及Slave_SQL_Running进程必须正常运行

 

主从同步参数优化

 

主从同步参数优化,修改my.cnf文件

 

1.参数进行忽略(从库配置文件)

当业务中出现无需同步的数据表时,可以选择replicate_wild_ignore_table=db.table参数进行忽略(从库配置文件)

 

2.跳过指定错误(从库配置文件)

slave-skip-errors = 1062,1053    #根据业务类型选择

1007:数据库已存在,创建数据库失败    

1008:数据库不存在,删除数据库失败    

1050:数据表已存在,创建数据表失败    

1051:数据表不存在,删除数据表失败    

1054:字段不存在,或程序文件跟数据库有冲突    

1060:字段重复,导致无法插入    

1061:重复键名    

1068:定义了多个主键    

1094:位置线程ID    

1146:数据表缺失,请恢复数据库    

1053:复制过程中主服务器宕机    

1062:主键冲突

 

3.删除同步日志(主库配置文件)

Master库中的同步日志需要及时删除

Expire_logs_days = 7   #删除7天前的同步日志

 

主从复制原理简介

 

 

  1. slave库手动执行change  master to 语句连接master库,提供了连接的用户一切条件(user 、pwd、port、ip),并且让slave知道,二进制日志的起点位置(file名 position 号),同时开启start  slave

  2. slave库的IO线程和主库的dump线程建立连接

  3. slave库根据change  master  to 语句提供的file名和position号,IO线程向主库发起binlog的请求

  4. master库dump线程根据从库的请求,将本地binlog发给slave库IO线程

  5. slave库IO线程接收binlog并存放到本地relay-log中

  6. slave库SQL线程应用relay-log,默认情况下,已经应用过的relay-log 会自动被清理

 

  • 主主同步架构介绍

 

 

由于keepalived会检测mysql运行状态,在重启mysql时注意,先停止keepalived服务,确认mysql运行正常时,再启动keepalived。

 

主主配置方式和上文介绍的主从配置类似,即master复制slave数据,slave复制master数据。

 

Keepalived实现自动切换

 

Keepalived是实现集群高可用的服务软件,通过虚拟路由冗余协议(vrrp),将N台提供相同服务的路由组成一个路由组,可以有一个master和多个backup,master上是对外提供服务的虚拟ip,当backup收不到master发送的vrrp包时就认为master宕掉,此时选举一个backup来充当master并重新绑定虚拟ip,来保证服务高可用性。

 

1.用户自行下载相关版本并安装

# cd keepalived

# ./configure --prefix=/usr/local/keepalived   (安装路径)

# make && make install

 

2.设置系统为系统服务方便启动停止

mkdir /etc/keepalived 

cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/ 

cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/

ln -s /usr/local/sbin/keepalived /usr/sbin/

ln -s /usr/local/keepalived/sbin/keepalived /sbin/

 

3.建议将keepalived设置为自启服务

chkconfig keepalived on

 

4.Keepalived配置管理

修改/etc/keepalived/keepalived.conf文件

 

5.编写keepalived执行脚本

注意:授权chmod +x /etc/keepalived/mysql_check.sh

 

6.可配置邮件发送提醒

编写sendmail.pl脚本,注意:授权chmod +x /etc/keepalived/sendmail.pl

 

7.keepalived配置文件

global_defs {       #全局配置 

     notification_email {          #定义报警邮件地址 

         root@localhost

     } 

    notification_email_from root@localhost   #定义发送邮件的地址 

    smtp_server 127.0.0.1                    #邮箱服务器 

    smtp_connect_timeout 30            #定义超时时间 

    router_id LVS_DEVEL                #定义路由标识信息,建议使用主机名

vrrp_script chk_mysql  {

    script  "/etc/keepalived/mysql_check.sh"

    interval 2

    weight  -20

}

vrrp_instance VI_83 {    #定义实例

    state MASTER        #状态参数 master/backup 只是说明

    interface eth0      #虚ip绑定网卡位置

    virtual_router_id 83       #同一个集群id一致

    priority 100               #priority值最大的将成为master

    mcast_src_ip 192.168.0.1   #发送组播包的地址,不设置则使用网卡默认ip

    advert_int 1       #主备通讯间隔s

    authentication {    #设置认证

        auth_type PASS

        auth_pass 1111

    }

    track_script {

        chk_mysql

    }

    virtual_ipaddress {  #虚拟ip

        192.168.0.0

    }

    notify_master /etc/keepalived/sendmail.pl  #邮件发送脚本

}

 

  • 一主多从架构部署介绍

 

 

应用服务器只配置mycat地址即可,mycat可以实现读写分离和故障切换。

 

Master负责写入,Slave负责读取,同时MySQL可以支持级联同步部署。

 

MySQL为保证事务的完整性,复制在slave上是串行化的,也就是多个master上的并行更新操作不能在同一slave上同时进行。

 

Mycat读写分离配置及优化

 

mycat可用于读写分离和数据切分的高可用中间件,并支持基于心跳检测的自动故障切换,mycat主要包含两个核心配置文件server.xml和schema.xml

 

1.server.xml配置优化

<user name=“user”>      <!—对客户端提供的用户名、密码 及表空间-->

<property name="password">******</property>

<property name="schemas">testdb</property>

<property name="readOnly">false</property> 

<!--readOnly设置成false,代表可进行读写操作-->

</user>

 

2. schema.xml配置优化

<schema name=“testdb" checkSQLschema="false" sqlMaxLimit="100" dataNode=“dn1">

</schema>

<dataNode name=“dn1" dataHost="host001" database=“db1" />

<dataHost name=" host001" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="2"  slaveThreshold="100">

<heartbeat>show slave status </heartbeat>

<writeHost host=“mysql-1” url=“192.168.0.1:3306” user=“user” password=“******”>

<!—master可读、写操作,slave只读-->

              <readHost host="mysql-1" url="192.168.0.1:3306" user=“user" password="******" />

              <readHost host="mysql-2" url="192.168.0.2:3306" user=“user" password="******" />

</writeHost>

<writeHost host=“mysql-2” url=“192.168.0.2:3306” user=“user”password=“******”>

<!—master故障,切换slave读写-->

<readHost host="mysql-2" url="192.168.0.2:3306" user=“user" password="******" />

</writeHost>

</dataHost>

 

参数说明:

 

writeType属性负载均衡类型,目前的取值有3种:

 

  1. writeType="0", 所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后以切换后的为准,切换记录在配置文件中:dnindex.properties.

  2. writeType="1",所有写操作都随机的发送到配置的writeHost,1.5以后废弃不推荐。

  3. writeType="2",不执行写操作

 

switchType指的是切换的模式,目前的取值也有4种:

 

  1. switchType='-1' 表示不自动切换

  2. switchType='1' 默认值,表示自动切换

  3. switchType='2' 基于MySQL主从同步的状态决定是否切换,心跳语句为 show slave status

  4. switchType='3'基于MySQL galary cluster的切换机制(适合集群)(1.4.1),心跳语句为 show status like 'wsrep%'

 

负载均衡类型,目前的取值有4种:  

 

  1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。

  2. balance="1",所有读操作都随机的发送到readHost。全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。

  3. balance="2",所有读操作都随机的在writeHost、readhost上分发。

  4. balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力

 

  • Tomcat优化分享

 

1.内存优化

 

内存优化主要是对启动参数优化,启动脚本 catalina.sh 中设置 java_OPTS 参数

 

JAVA_OPTS参数说明:

 

-server 启用jdk 的 server 版

-Xms java虚拟机初始化时的最小内存

-Xmx java虚拟机可使用的最大内存

-XX: PermSize 内存永久保留区域

-XX:MaxPermSize 内存最大永久保留区域

 

配置示例:

 

JAVA_OPTS=’-Xms1024m -Xmx2048m -XX: PermSize=256M -XX:MaxNewSize=256m -XX:MaxPermSize=256m’

 

说明:其内存的配置需要根据服务器(或虚拟机)的实际内存来配置;重启tomcat生效。

 

2.线程优化

 

修改server.xml配置文件:

maxThreads = “500”    

//最大线程数,默认200,没有最理想的值,需要不断调整、优化,道道最合理的配置

//当系统需要大量计算时,响应时间取决于cup运算能力,此时maxThreads尽量设小,降低同一时间内争抢cup的线程数

//当系统主要是I/O或操作数据库时,响应时间取决于外部资源等待,此时maxThreads尽量设大,提高同时处理请求的个数

minSpareThreads=“50“    //初始化时创建的线程数,默认值为4

maxSpareThreads="500“  //一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程

acceptCount=“500”    

//当所有处理的线程都正在使用时,在队列中排队请求的最大数目,默认值为10,

//超出队列数,任何请求都会被拒绝一般设置跟maxThreads一样大,

//这个值应该是主要根据应用的访问峰值与平均值来权衡配置的

 

3.其他常用优化

 

maxPostSize=“-1”   //POST请求数据大小限制,默认2M,tomcat-7.0.63之前设置为”0”表示不限制,7.0.63版本之后,设置为负数,表示不显示

connectionTimeout=“20000”  //设置连接超时时间毫秒值

maxHttpHeaderSize=“8192”  //HTTP请求和响应头的最大量,以字节为单位,默认值为4096字节

URIEncoding=“UTF-8“ //Tomcat中配置URIEncoding=”UTF-8”来进行中文的处理

enableLookups=“false”  //如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址,为了提高处理能力,应设置为 false

 

3.优化案例分析

 

上面章节介绍了架构演变、数据库及相关组件部署优化、Tomcat应用优化等内容,本章节以实际架构案例分析,讲解上述内容在实际架构中的应用。

 

 

案例架构采用典型的分层服务架构(三层),即接入层、应用层和数据层,所有应用服务均使用集群部署,保证服务的高可用性。

 

数据层:

 

案例系统中,数据读取业务偏多,故考虑使用使用mycat做读写分离,两台数据库同时对外提供读取业务,其中一台主服务器提供写入操作,当master节点宕机之后,mycat组件检测到服务状态,并将读写能力全部切换至slave节点,保证系统的运行

Mycat组件进行读写分离和故障切换,所有应用服务连接keepalived对外提供的虚拟ip进行数据库操作,Mycat本身也是一个高可用集群架构。

 

应用层:

 

内网负责均衡服务除了可以负载业务的请求之外,还将DMZ区与内网隔离,避免代理服务器直接请求内网应用,负载均衡Nginx使用时,应当根据集群中服务器的性能、部署服务等,合理进行权重分配。

 

公共组件应用服务器将组件服务通过分布式系统发布,供其他业务系统使用;也可为移动端提供公共服务组件。

 

应用集群服务器可能存在文件上传业务,当文件上传至服务器后,注意集群之间的数据同步问题。

 

接入层:

 

DMZ区:为了解决外部网络不能访问内部网络服务器的问题,而设立的一个非安全系统与安全系统之间的缓冲区。由于DMZ区的特殊性,与Internet相比,DMZ可以提供更高的安全性,但是其安全性比内部网络低,所以在部署时,特别注意网络上的连通性关系。 

 

DMZ区左侧代理服务器主要负责代理推送和设备管理服务对互联网的请求,用户也可直接通过互联网访问到该代理集群服务器,可以用作内部自建应用市场等互联网服务;DMZ区右侧代理服务器主要通过安全网关通道将业务请求代理至内网,安全网关只对其白名单中的服务器和端口进行开放。

 

*1.注意图中①②③④标注位置的网络开通

*2.图中使用keepalived做高可用架构的地方如图中的⑤标注位置,需要注意虚拟ip的使用

 

应用部署和优化的方法多种多样,其本身就是一个不断尝试、实践、总结的过程,很多相关的技术方案和阅读资料只能用作借鉴参考,我们需要针对不同企业的特点来制定相关方案,不断去优化尝试,才能最终解决问题。

 

关于作者:冬火,现任普元移动团队开发运维工程师,主攻Java Web开发、系统架构设计和维护,先后参与多家金融机构移动平台系统的开发和架构设计运维工作。专注服务部署和优化、网络技术爱好者,移动平台架构的践行者。

关于EAWorld:微服务,DevOps,数据治理,移动架构原创技术分享。长按二维码关注!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!