网站性能优化小结和spring整合redis
现在越来越多的地方需要非关系型数据库了,最近网站优化,当然从页面到服务器做了相应的优化后,通过在线网站测试工具与之前没优化对比,发现有显著提升。
服务器优化目前主要优化tomcat,在tomcat目录下的server.xml文件配置如下内容:
- <Connector port="1818"
- protocol="HTTP/1.1"
- maxHttpHeaderSize="8192"
- maxThreads="1000"
- minSpareThreads="100"
- maxSpareThreads="1000"
- minProcessors="100"
- maxProcessors="1000"
- enableLookups="false"
- compression="on"
- compressionMinSize="2048"
- compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
- connectionTimeout="20000"
- URIEncoding="utf-8"
- acceptCount="1000"
- redirectPort="8443"
- disableUploadTimeout="true"/>
- 参数说明:
- Protocol 采用的协议//可将HTTP/1.1改为org.apache.coyote.http11.Http11NioProtocol 启动NIO模式
- maxHttpHeaderSize 代表请求和响应的HTTP首部的最大长度,单位是字节。如果不指定,该属性将被设为4096(4K)。
- maxThreads 客户请求最大线程数
- minSpareThreads Tomcat初始化时创建的 socket 线程数
- maxSpareThreads Tomcat连接器的最大空闲 socket 线程数
- enableLookups 若设为true, 则支持域名解析,可把 ip 地址解析为主机名
- redirectPort 在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口
- acceptAccount 监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads )
- connectionTimeout 连接超时
- minProcessors 服务器创建时的最小处理线程数
- maxProcessors 服务器同时最大处理线程数
- URIEncoding URL统一编码
- compression 打开压缩功能
- compressionMinSize 启用压缩的输出内容大小,这里面默认为2KB
- compressableMimeType 压缩类型
- connectionTimeout 定义建立客户连接超时的时间. 如果为 -1, 表示不限制建立客户连接的时间
网站性能优化,参照了《高性能网站建设指南》这本书和部分知识博客
就我们项目而言,我参照这本书,按照这么几个规范进行,书上提出了,优化十四个建议,不过,并不是十四建议通通采纳,网站性能一定能上升的非常好,要结合项目的实际情况。
这是我们采取的前端性能优化措施:
1.减少http请求 比如外部的css,js和图片等组件,访问一个网站时,这些组件都会被加载,组件过多,加载时间长,特别是图片等,所以减少http请求,可有效提高网站性能
2.头部引用外部css和底部引用js 初次点击进入网站,网站的背景图和其他非js效果的css效果会最先加载,j如果不放在头部的话,首先看到的就是空白,然后就有相应的css渲染效果,底部引用js,在视觉上让用户觉得加载快了,而且外部的css和js方便管理,内联的js和css过度使用,会导致页面代码重构和后续其他人开发,会比较吃力。同时这样做也是一种很好的规范。js放在尾部也就是</body>标签前,它会被最后加载,如果统统放在<head></head>下,并行加载,会导致阻塞后面文件的下载和会导致后面的css渲染变慢。因此放在尾部是比较好的选择。
3.压缩组件。目前通过tomcat中的上述配置实行gzip压缩
4.合并css和js文件 大家要知道加载一个js和加载两个js文件的速度完全是不一样的,尽快前者js文件的容量大于后者两个。总之一个请求的速度总会大于两个请求的速度。
从http请求的角度解析,客户端发出请求给服务器,服务器响应数据返回给客户端。一个请求到响应的速度始终大于两个请求。还是回到之前的减少http请求。另外合并不代表一个无关的js和另外好几个无关js合在一起,这样不利于后面管理,合并应该是相关js函数合在一起,不相关js文件如果内容很多,可不必合并,如果只有单独的一两个函数,可与另外一两个函数合并,切记要写注释,同时合并js,不可合并过多
后台采取的措施:
1.sql优化 查询尽量查出符合需要的字段,严禁用*,同时in和not in尽可能用exists和not exists替换等
2.Java代码复用,减少冗余,特别是后台很多重复的service,将其公共通用部分写成一个函数,以供用到的Controller进行复用(当然这对于优化网站性能方面,可能帮助不大,但有利于后续开发的进行)
下面进行正式的spring整合redis:
为什么要用redis?
就目前我们项目而言,打开pms后台加载过慢,当然原因包括没用的js过多引用进来加载时间长,自然速度慢,频繁的http请求,布局不合理(js全部放在头部),sql没有优化等。
上述问题都可以解决。
回到上述问题,为什么使用redis。使用redis做缓存,R可以将所有的数据先保存到缓存中,然后再存入mysql中,减小数据库压力,提高效率 。
redis为什么访问数据的速度大于mysql?
因为前者访问的是内存,后者是磁盘
因为cpu是直接与内存进行数据交互的
演示实例:
注意ssm框架,jdk8,tomcat8服务器
一、pom依赖
- <!-- redis -->
- <dependency>
- <groupId>redis.clients</groupId>
- <artifactId>jedis</artifactId>
- <version>2.1.</version>
- </dependency>
- <!-- spring-data-redis -->
- <dependency>
- <groupId>org.springframework.data</groupId>
- <artifactId>spring-data-redis</artifactId>
- <version>1.0..RELEASE</version>
- </dependency>
- <!-- mybatis-ehcache -->
- <dependency>
- <groupId>org.mybatis.caches</groupId>
- <artifactId>mybatis-ehcache</artifactId>
- <version>1.0.</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid</artifactId>
- <version>1.0.</version>
- </dependency>
二、对应的application-config.xml配置
- <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
- <property name="maxIdle" value="" />
- <property name="testOnBorrow" value="true"/>
- </bean>
- <!-- 连接池配置,类似数据库连接池 -->
- <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
- <property name="hostName" value="192.168.126.128"></property>
- <property name="port" value=""></property>
- <property name="password" value=""></property>
- <property name="poolConfig" ref="poolConfig"></property>
- </bean>
- <!-- 调用连接池工厂配置 -->
- <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
- <property name="connectionFactory" ref="connectionFactory"></property>
- <!-- 如果不配置Serializer,那么存储的时候智能使用String,如果用User类型存储,那么会提示错误User can't cast
- to String!!! -->
- <property name="keySerializer">
- <bean
- class="org.springframework.data.redis.serializer.StringRedisSerializer" />
- </property>
- <property name="valueSerializer">
- <bean
- class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
- </property>
- </bean>
- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
- <!-- 基本属性 url、user、password -->
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/test" />
- <property name="username" value="root" />
- <property name="password" value="" />
- <property name="filters" value="stat,config" />
- <!-- 配置初始化大小、最小、最大 -->
- <property name="initialSize" value="" />
- <property name="minIdle" value="" />
- <property name="maxActive" value="" />
- <!-- 配置获取连接等待超时的时间 -->
- <property name="maxWait" value="" />
- <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
- <property name="timeBetweenEvictionRunsMillis" value="" />
- <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
- <property name="minEvictableIdleTimeMillis" value="" />
- <property name="validationQuery" value="SELECT 'x' FROM DUAL" />
- <property name="testWhileIdle" value="true" />
- <property name="testOnBorrow" value="false" />
- <property name="testOnReturn" value="false" />
- <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
- <property name="poolPreparedStatements" value="true" />
- <property name="maxPoolPreparedStatementPerConnectionSize" value="" />
- <!-- 超过时间限制是否回收 -->
- <property name="removeAbandoned" value="true" />
- <!-- 超时时间;单位为秒。180秒=3分钟 -->
- <property name="removeAbandonedTimeout" value="" />
- <!-- 关闭abanded连接时输出错误日志 -->
- <property name="logAbandoned" value="true" />
- <!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
- <!-- property name="filters" value="stat" /-->
- </bean>
三、JavaBean
记得一定要实现序列化,否则会报错
- package com.tp.soft.entity;
- import java.io.Serializable;
- public class User implements Serializable{
- /**
- *
- */
- private static final long serialVersionUID = -1695973853274402680L;
- private int userid;
- private String login_name;
- private String login_pwd;
- public User() {
- }
- public User(int userid, String login_name, String login_pwd) {
- super();
- this.userid = userid;
- this.login_name = login_name;
- this.login_pwd = login_pwd;
- }
- public int getUserid() {
- return userid;
- }
- public void setUserid(int userid) {
- this.userid = userid;
- }
- public String getLogin_name() {
- return login_name;
- }
- public void setLogin_name(String login_name) {
- this.login_name = login_name;
- }
- public String getLogin_pwd() {
- return login_pwd;
- }
- public void setLogin_pwd(String login_pwd) {
- this.login_pwd = login_pwd;
- }
- }
四、接口类
- package com.tp.soft.dao;
- import com.tp.soft.entity.User;
- public interface UserMapper {
- public User getUserById(int id);
- }
五、接口对应的xml文件
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
- <mapper namespace="com.tp.soft.dao.UserMapper">
- <!-- 缓存类配置 -->
- <cache type="com.tp.soft.redis.RedisCache" />
- <select id="getUserById" parameterType="int" resultType="user" useCache="true">
- select * from AU_USER where userid = #{id}
- </select>
- </mapper>
六、mybatis-config.xm配置
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <settings>
- <!-- 二级缓存开启 -->
- <setting name="cacheEnabled" value="true"/>
- <setting name="lazyLoadingEnabled" value="false"/>
- <setting name="aggressiveLazyLoading" value="true"/>
- </settings>
- <!-- 配置映射类的别名 -->
- <typeAliases>
- <!-- 配置entity下的所有别名 别名首字母小写 -->
- <package name="com.tp.soft.entity" />
- </typeAliases>
- </configuration>
七、service和service实现类
- package com.tp.soft.service;
- import com.tp.soft.entity.User;
- public interface UserSvc {
- public User getUser(int id);
- }
- package com.tp.soft.service.impl;
- import javax.annotation.Resource;
- import org.springframework.dao.DataAccessException;
- import org.springframework.stereotype.Service;
- import com.tp.soft.dao.UserMapper;
- import com.tp.soft.entity.User;
- import com.tp.soft.service.UserSvc;
- @Service("userService")
- public class UserSvcImpl implements UserSvc{
- @Resource
- private UserMapper userMapper;
- public User getUser(int id) {
- User user = null;
- try{
- user = userMapper.getUserById(id);
- }catch (DataAccessException e) {
- System.out.println(e.getLocalizedMessage());
- }
- return user;
- }
- }
八、Controller
- package com.tp.soft.controller;
- import javax.annotation.Resource;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
- import com.tp.soft.entity.User;
- import com.tp.soft.service.UserSvc;
- @Controller
- public class UserController {
- @Resource
- private UserSvc userSvc;
- @RequestMapping(value="/QueryUser")
- public String toQueryUser(int id,Model model){
- User user = userSvc.getUser(id);
- System.out.println(user.getLogin_name());
- model.addAttribute("user", user);
- return "/pc/userTest";
- }
- }
九、需用到的util
- package com.tp.soft.redis;
- import redis.clients.jedis.Jedis;
- import redis.clients.jedis.JedisPool;
- import redis.clients.jedis.JedisPoolConfig;
- public class JedisUtil {
- private static String ADDR = "192.168.126.128";
- private static int PORT = 6379;
- private static String AUTH = "123456";
- private static int MAX_ACTIVE = 1024;
- private static int MAX_IDLE = 200;
- private static int MAX_WAIT = 10000;
- private static int TIMEOUT = 10000;
- private static boolean TEST_ON_BORROW = true;
- private static JedisPool jedisPool = null;
- static {
- try{
- JedisPoolConfig config = new JedisPoolConfig();
- config.setMaxIdle(MAX_IDLE);
- config.setTestOnBorrow(TEST_ON_BORROW);
- jedisPool = new JedisPool(config,ADDR,PORT,TIMEOUT,AUTH);
- }catch (Exception e) {
- e.printStackTrace();
- }
- }
- public synchronized static Jedis getJedis(){
- try{
- if(jedisPool != null){
- Jedis jedis = jedisPool.getResource();
- return jedis;
- }else{
- return null;
- }
- }catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- public static void returnResource(final Jedis jedis){
- if(jedis != null){
- jedisPool.returnResource(jedis);
- }
- }
- }
- package com.tp.soft.redis;
- import java.util.concurrent.locks.ReadWriteLock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- import org.apache.ibatis.cache.Cache;
- /*
- * 使用第三方缓存服务器,处理二级缓存
- */
- public class RedisCache implements Cache {
- private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
- private String id;
- public RedisCache(final String id) {
- if (id == null) {
- throw new IllegalArgumentException("Cache instances require an ID");
- }
- this.id = id;
- }
- public String getId() {
- return this.id;
- }
- public void putObject(Object key, Object value) {
- JedisUtil.getJedis().set(SerializeUtil.serialize(key.toString()),
- SerializeUtil.serialize(value));
- }
- public Object getObject(Object key) {
- Object value = SerializeUtil.unserialize(JedisUtil.getJedis().get(
- SerializeUtil.serialize(key.toString())));
- return value;
- }
- public Object removeObject(Object key) {
- return JedisUtil.getJedis().expire(
- SerializeUtil.serialize(key.toString()), 0);
- }
- public void clear() {
- JedisUtil.getJedis().flushDB();
- }
- public int getSize() {
- return Integer.valueOf(JedisUtil.getJedis().dbSize().toString());
- }
- public ReadWriteLock getReadWriteLock() {
- return readWriteLock;
- }
- }
- package com.tp.soft.redis;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- public class SerializeUtil {
- public static byte[] serialize(Object object) {
- ObjectOutputStream oos = null;
- ByteArrayOutputStream baos = null;
- try {
- // 序列化
- baos = new ByteArrayOutputStream();
- oos = new ObjectOutputStream(baos);
- oos.writeObject(object);
- byte[] bytes = baos.toByteArray();
- return bytes;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- public static Object unserialize(byte[] bytes) {
- if (bytes == null)
- return null;
- ByteArrayInputStream bais = null;
- try {
- // 反序列化
- bais = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = new ObjectInputStream(bais);
- return ois.readObject();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- }
十、演示效果
目前本人也是刚刚用到没多久,如果那里有问题,欢迎大家指教
其实性能的瓶颈和mysql有关系,目前对于mysql相关的原理等不是特别了解,需后面多加努力学习
网站性能优化小结和spring整合redis的更多相关文章
- 网站性能优化(Yahoo 35条)
Yahoo 网站性能优化 35条 一.内容部分 尽量减少 HTTP请求 减少 DNS查找 避免跳转 缓存 Ajxa 推迟加载 提前加载 减少 DOM元素数量 用域名划分页面内容 使 frame数量最少 ...
- Yahoo团队经验:网站性能优化的34条黄金法则
Yahoo团队总结的关于网站性能优化的经验,非常有参考价值.英文原文:http://developer.yahoo.com/performance/rules.html 1.尽量减少HTTP请求次数 ...
- 网站性能优化实战——从12.67s到1.06s的故事
文章摘自https://juejin.im/post/5b0b7d74518825158e173a0c 作为互联网项目,最重要的便是用户体验.在举国“互联网+”的热潮中,用户至上也已经被大多数企业所接 ...
- Spring整合Redis&JSON序列化&Spring/Web项目部署相关
几种JSON框架用法和效率对比: https://blog.csdn.net/sisyphus_z/article/details/53333925 https://blog.csdn.net/wei ...
- Yahoo网站性能优化的34条规则
摘自:http://blog.chinaunix.net/uid/20714478/cid-74195-list-1.html Yahoo网站性能优化的34条规则 1.尽量减少HTTP请求次数 终端用 ...
- input屏蔽历史记录 ;function($,undefined) 前面的分号是什么用处 JSON 和 JSONP 两兄弟 document.body.scrollTop与document.documentElement.scrollTop兼容 URL中的# 网站性能优化 前端必知的ajax 简单理解同步与异步 那些年,我们被耍过的bug——has
input屏蔽历史记录 设置input的扩展属性autocomplete 为off即可 ;function($,undefined) 前面的分号是什么用处 ;(function($){$.ex ...
- Yahoo! 35条网站性能优化建议
Yahoo! 35条网站性能优化建议 Yahoo!的 Exceptional Performance团队为改善 Web性能带来最佳实践.他们为此进行了一系列的实验.开发了各种工具.写了大量的文章和博客 ...
- Yslow网站性能优化工具
Yslow是一款网站性能优化的插件:
- asp.net网站性能优化2则
摘要:Web服务器的性能优化有很多资料介绍了,多台主机负载均衡,查询结果的多级缓 存,数据库索引优化等都是常见的优化手段.随着后端优化空间越来越小,现在越来越多 的网站更注重前端性能的优化,就是浏览器 ...
随机推荐
- 无法从其“Checked”属性的字符串表示形式“checked”创建“System.Boolean”类型
如果你要在后台进行设置的话...在<input type="radio" id="dd" name="dd" runat=" ...
- 使用 Immutable Subject 来驱动 Angular 应用
现状 最近在重构手上的一个 Angular 项目,之前是用的自己写的一个仿 Elm 架构的库来进行的状态管理,期间遇到了这些痛点: 样板代码太多 异步处理太过繁琐 需要单独维护一个 npm 包 其中, ...
- C++桥接模式【转】
https://www.cnblogs.com/jiese/p/3164940.html 将抽象部份与它的实现部份分离,使它们都可以独立地变化. 桥接模式号称设计模式中最难理解的模式之一,关键就是这个 ...
- 通过jQuery制作电子时钟表的代码
源码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <titl ...
- 用 JS 写 (轮播图 / 选项卡 / 滑动门)
页面中经常会用到各式各样的轮播图,今天贺贺为大家介绍一种常用的方法,对于JS我们需要举一反三,一种方法可以对多个轮播样式进行渲染. <head> <meta charset=&quo ...
- VUE 实现复制内容到剪贴板功能
注: 依赖第三方插件 clipboard 一.安装插件 npm install vue-clipboard2 --save 二.全局注入(main.js) import VueClipboard fr ...
- javascript arguments参数问题
function f(a, b, c){ alert(arguments.length); // result: "2" a = 100; alert(arguments[0]); ...
- OSPF协议总结
总结: 1.ospf协议报文不会泛洪扩散,而是逐级路由器处理后,再从所有ospf启用端口发送出去,也就是说,只能从邻居接收到ospf报文,报文的源ip是邻居的ip地址,目的ip是组播ip. 2.开启o ...
- Python中列表
names=["Linda","Lily","Lucy","Grace","Paul"] #切片 p ...
- Info.plist的CFBundleIdentifier、CFBundleName、BundleDisplayName
plist关键字段: CFBundleIdentifier:应用包名.唯一标识 CFBundleVersion:文件版本号,可以每次发版本递增 CFBundleShortVersionString:a ...