加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

网站性能优化小结和spring整合redis

发布时间:2020-12-15 07:10:42 所属栏目:Java 来源:网络整理
导读:现在越来越多的地方需要非关系型数据库了,最近网站优化,当然从页面到服务器做了相应的优化后,通过在线网站测试工具与之前没优化对比,发现有显著提升。 服务器优化目前主要优化tomcat,在tomcat目录下的server.xml文件配置如下内容: Connector port="1818"

现在越来越多的地方需要非关系型数据库了,最近网站优化,当然从页面到服务器做了相应的优化后,通过在线网站测试工具与之前没优化对比,发现有显著提升。

服务器优化目前主要优化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.0</version>  
        </dependency>
        <!-- spring-data-redis -->
         <dependency>
                <groupId>org.springframework.data</groupId>
              <artifactId>spring-data-redis</artifactId>
             <version>1.0.2.RELEASE</version>
        </dependency>
            <!-- mybatis-ehcache -->
        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>24</version>
        </dependency>

?

二、对应的application-config.xml配置

 <bean id="poolConfig" class=redis.clients.jedis.JedisPoolConfig">
        <property name=maxIdle" value=1000" />
        <property name=testOnBorrowtrue"/>
    </bean>

<!-- 连接池配置,类似数据库连接池 -->
    <bean id=connectionFactoryorg.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
        <property name=hostName"192.168.126.128"></property>
        <property name=port6379password123456"  ref="></property> 
        
    </bean>

    <!-- 调用连接池工厂配置 -->
    <bean id=redisTemplateorg.springframework.data.redis.core.RedisTemplate"></property>

       <!--  如果不配置Serializer,那么存储的时候智能使用String,如果用User类型存储,那么会提示错误User can't cast   
        to String!!!   -->
         <property name=keySerializer">  
            <bean  
            org.springframework.data.redis.serializer.StringRedisSerializer" />  
        </property>  
        <property name=valueSerializerbean  
                org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />  
        </property> 
</bean>
 

    

    <bean id=dataSourcecom.alibaba.druid.pool.DruidDataSource" init-method=init" destroy-method=close"> 
        <!-- 基本属性 url、user、password -->
        <property name=driverClassNamecom.mysql.jdbc.Driver"/>
        <property name=urljdbc:mysql://localhost:3306/testusername"root1234filtersstat,config" />
        
        <!-- 配置初始化大小、最小、最大 -->
        <property name=initialSize1minIdle" /> 
        <property name=maxActive40" />
     
        <!-- 配置获取连接等待超时的时间 -->
        <property name=maxWait60000" />
     
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name=timeBetweenEvictionRunsMillis" />
     
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name=minEvictableIdleTimeMillis300000" />
      
        <property name=validationQuerySELECT 'x' FROM DUALtestWhileIdlefalsetestOnReturn" />
     
        <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
        <property name=poolPreparedStatementsmaxPoolPreparedStatementPerConnectionSize20" />
        
        <!-- 超过时间限制是否回收 --> 
        <property name=removeAbandoned" /> 
        <!-- 超时时间;单位为秒。180秒=3分钟 --> 
        <property name=removeAbandonedTimeout180" /> 
        <!-- 关闭abanded连接时输出错误日志 --> 
        <property name=logAbandoned" />
     
        <!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
        <!-- property name=stat" /--> 
    </bean>
    

    

?

三、JavaBean

记得一定要实现序列化,否则会报错

package com.tp.soft.entity;

import java.io.Serializable;

public class User implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = -1695973853274402680L;
    
    int userid;
    
    private String login_name;
    
     String login_pwd;

    
    public User() {
        
    }


    public User( userid,String login_name,String login_pwd) {
        super();
        this.userid = userid;
        this.login_name = login_name;
        this.login_pwd = login_pwd;
    }


     getUserid() {
        return userid;
    }


    void setUserid( userid) {
         String getLogin_name() {
         login_name;
    }


    void setLogin_name(String login_name) {
         String getLogin_pwd() {
         setLogin_pwd(String login_pwd) {
         login_pwd;
    }


}

四、接口类

 com.tp.soft.dao;

 com.tp.soft.entity.User;

interface UserMapper {
    public User getUserById( 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实现类

 com.tp.soft.service;

 UserSvc {
    public User getUser( id);
}
 com.tp.soft.service.impl;

 javax.annotation.Resource;

 org.springframework.dao.DataAccessException;
 org.springframework.stereotype.Service;

 com.tp.soft.dao.UserMapper;
 com.tp.soft.entity.User;
 com.tp.soft.service.UserSvc;

@Service("userService")
class UserSvcImpl  UserSvc{

    @Resource
     UserMapper userMapper;
    
     id) {
        User user = null;
        try{
            user = userMapper.getUserById(id);
        }catch (DataAccessException e) {
            System.out.println(e.getLocalizedMessage());
        }
         user;
    }

}

?

八、Controller

 com.tp.soft.controller;



 org.springframework.stereotype.Controller;
 org.springframework.ui.Model;
 org.springframework.web.bind.annotation.RequestMapping;

 com.tp.soft.service.UserSvc;

@Controller
class UserController {
    
    @Resource
     UserSvc userSvc;
    
    @RequestMapping(value="/QueryUser")
    public String toQueryUser( id,Model model){
 
        
        User user = userSvc.getUser(id);

        System.out.println(user.getLogin_name());
        model.addAttribute("user",user);
        return "/pc/userTest";
    }
}

?

九、需用到的util

 com.tp.soft.redis;

 redis.clients.jedis.Jedis;
 redis.clients.jedis.JedisPool;
 redis.clients.jedis.JedisPoolConfig;

 JedisUtil {
    static String ADDR = "192.168.126.128";
    int PORT = 6379static String AUTH = "123456"int MAX_ACTIVE = 1024int MAX_IDLE = 200int MAX_WAIT = 10000int TIMEOUT = 10000boolean TEST_ON_BORROW = truestatic JedisPool jedisPool = static {
        {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(MAX_IDLE);

            config.setTestOnBorrow(TEST_ON_BORROW);
            jedisPool =  JedisPool(config,ADDR,PORT,TIMEOUT,AUTH);
        } (Exception e) {
            e.printStackTrace();
        }
    }
    
    synchronized  Jedis getJedis(){
        {
            if(jedisPool != ){
                Jedis jedis = jedisPool.getResource();
                 jedis;
            }else{
                return ;
            }
        } (Exception e) {
            e.printStackTrace();
            ;
        }
    }
    
    void returnResource(final Jedis jedis){
        if(jedis != ){
            jedisPool.returnResource(jedis);
        }
    }
}
 java.util.concurrent.locks.ReadWriteLock;
 java.util.concurrent.locks.ReentrantReadWriteLock;

 org.apache.ibatis.cache.Cache;

/*
 * 使用第三方缓存服务器,处理二级缓存
 */
class RedisCache  Cache {
    final ReadWriteLock readWriteLock =  ReentrantReadWriteLock();

     String id;

    public RedisCache( String id) {
        if (id == ) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        this.id = id;

    }

     String getId() {
        this.id;
    }

     putObject(Object key,Object value) {
        JedisUtil.getJedis().set(SerializeUtil.serialize(key.toString()),SerializeUtil.serialize(value));

    }

     Object getObject(Object key) {
        Object value = SerializeUtil.unserialize(JedisUtil.getJedis().get(
                SerializeUtil.serialize(key.toString())));
         value;

    }

     Object removeObject(Object key) {
         JedisUtil.getJedis().expire(
                SerializeUtil.serialize(key.toString()),0);

    }

     clear() {
        JedisUtil.getJedis().flushDB();
    }

     getSize() {
         Integer.valueOf(JedisUtil.getJedis().dbSize().toString());
    }

     ReadWriteLock getReadWriteLock() {
         readWriteLock;
    }

}
 java.io.ByteArrayInputStream;
 java.io.ByteArrayOutputStream;
 java.io.ObjectInputStream;
 java.io.ObjectOutputStream;

 SerializeUtil {
    byte[] serialize(Object object) {
        ObjectOutputStream oos = ;
        ByteArrayOutputStream baos =  {
            // 序列化
            baos =  ByteArrayOutputStream();
            oos =  ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes = baos.toByteArray();
             bytes;
        }  (Exception e) {
            e.printStackTrace();
        }
        ;
    }

    static Object unserialize([] bytes) {
        if (bytes == )
            ;
        ByteArrayInputStream bais =  反序列化
            bais =  ByteArrayInputStream(bytes);
            ObjectInputStream ois =  ObjectInputStream(bais);
             ois.readObject();
        } ;
    }
}

十、演示效果

目前本人也是刚刚用到没多久,如果那里有问题,欢迎大家指教

其实性能的瓶颈和mysql有关系,目前对于mysql相关的原理等不是特别了解,需后面多加努力学习

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读