AI智能
改变未来

网站优化

[TOC]

面对并发是如何优化网站性能的?

每个项目都会随着用户和数据的增长调整架构,来面对未来的问题

随着用户的增加,平台开始变得卡顿,开始了问题排查和优化,下面就和大家聊聊是如何处理的吧。

Nginx

一个网站,核心会分为几部分:前端、后台服务、数据库,服务器。

我们最开始项目是打的jar包 ,一个tomcat支撑不了多少并发,

Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当然了,也可以将其改大。所以只能开始搭建集群。

搭建集群后引入了Nginx做反向代理,负载均衡也解决了,根据不同的服务器的性能做了权重,

果然增加了Nginx,做了负载之后,网站访问快了不少。

但是又迎来了Session共享的问题,我们将用户的会话信息放入redis,session共享搞定。

或者使用IPHash

IPhash对客户端请求的IP进行hash操作,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理,可以解决session不共享的问题。

接入层搞定了之后,发现论坛模块还是很慢。

慢SQL

开始排查日志,发现了一些SQL处理竟然要大于1S。

根本问题是做了联表查询,关联的表比较多,于是我们开始优化数据库结构,增加了许多冗余字段,

后面只用查询一个表了,从蜗速到现在几乎秒开了。

关于分类

从数据库查询优化到使用静态数据管理,因为几乎不会发生变化。

主从复制、读写分离

接入层的问题解决后,发现项目的压力瓶颈转移到了数据库上面,

开始还是单个数据库,但是读和写都在一个数据库,性能完全不太够用,

于是又用一台服务器开始做主从(吐槽:果然只要有钱,问题就好解决一些了),

MySQL的主从还是比较简单的,几个命令就搭建好了,然后我们使用了sharding jdbc来做读写分离。

写完之后,网站整体的性能都提高了。

mysql配置主从数据库

1.修改主服务器master:

#vi /etc/my.cnf[mysqld]log-bin=mysql-bin   //[必须]启用二进制日志server-id=222      //[必须]服务器唯一ID,默认是1,一般取IP最后一段

2.修改从服务器slave:

   #vi /etc/my.cnf[mysqld]log-bin=mysql-bin   //[不是必须]启用二进制日志server-id=226      //[必须]服务器唯一ID,默认是1,一般取IP最后一段

3.重启两台服务器的mysql

service mysqld restart;

4.在主服务器上建立帐户并授权slave:

#/usr/local/mysql/bin/mysql -uroot -pmttangmysql>GRANT REPLICATION SLAVE ON *.* to \'mysync\'@\'%\' identified by \'password\'; //一般不用root帐号

“%”表示所有客户端都可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。

5.登录主服务器的mysql,查询master的状态

mysql>show master status;+------------------+----------+--------------+------------------+| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |+------------------+----------+--------------+------------------+| mysql-bin.000004 |      308 |              |                  |+------------------+----------+--------------+------------------+1 row in set (0.00 sec)

注:执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化

6.配置从服务器Slave

mysql>change master to master_host=\'192.168.145.222\',master_user=\'username\',master_password=\'password\',master_log_file=\'mysql-bin.000004\',master_log_pos=308;   //注意不要断开,308数字前后无单引号。Mysql>start slave;    //启动从服务器复制功能

7.检查从服务器复制功能状态:

mysql> show slave status\\G*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 192.168.2.222  //主服务器地址Master_User: mysync   //授权帐户名,尽量避免使用rootMaster_Port: 3306    //数据库端口,部分版本没有此行Connect_Retry: 60Master_Log_File: mysql-bin.000004Read_Master_Log_Pos: 600     //#同步读取二进制日志的位置,大于等于Exec_Master_Log_PosRelay_Log_File: ddte-relay-bin.000003Relay_Log_Pos: 251Relay_Master_Log_File: mysql-bin.000004Slave_IO_Running: Yes    //此状态必须YESSlave_SQL_Running: Yes     //此状态必须YES......

注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。

以上操作过程,主从服务器配置完成。

Sharding-JDBC实现读写分离

技术选型:SpringBoot + Sharding-JDBC + MyBatis

使用Sharding-JDBC配置读写分离,优点在于数据源完全有Sharding托管,写操作自动执行master库,读操作自动执行slave库。不需要程序员在程序中关注这个实现了。

1. 核心jar包

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- sharding --><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1</version></dependency><!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version></dependency><!--阿里数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.14</version></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.60</version></dependency></dependencies>

2. yml文件配置

spring:main:allow-bean-definition-overriding: trueshardingsphere:datasource:names:master,slave# 主数据源master:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_master?characterEncoding=utf-8username: ****password: ****# 从数据源slave:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_slave?characterEncoding=utf-8username: ****password: ****masterslave:# 读写分离配置, 用于配置从库负载均衡算法类型,可选值:ROUND_ROBIN(轮询),RANDOM(随机)load-balance-algorithm-type: round_robin# 最终的数据源名称name: dataSource# 主库数据源名称master-data-source-name: master# 从库数据源名称列表,多个逗号分隔slave-data-source-names: slaveprops:# 开启SQL显示,默认false,在执行SQL时,会打印SQL,并显示执行库的名称sql:show: true

问题:读写分离架构中经常出现,那就是读延迟的问题如何解决?

刚插入一条数据,然后马上就要去读取,这个时候有可能会读取不到?

归根到底是因为主节点写入完之后数据是要复制给从节点的,读不到的原因就是说数据还没复制到从节点,你就已经去从节点读取了,肯定读不到。

mysql5.7 的主从复制是多线程了,意味着速度会变快,但是不一定能保证百分百马上读取到,这个问题我们可以有两种方式解决:

  (1)是否立马读取,业务层面妥协,是否操作完之后马上要进行读取

  (2)控制是否直接走主库,对于操作完马上要读出来的,且业务上不能妥协的,我们可以对于这类的读取直接走主库,当然Sharding-JDBC也是考虑到这个问题的存在,所以给我们提供了一个功能,可以让用户在使用的时候指定要不要走主库进行读取。在读取前使用下面的方式进行设置就可以了:

public List<UserInfo> getList() {// 强制路由主库HintManager.getInstance().setMasterRouteOnly();return this.list();}
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 网站优化