远程连接redis连接池总是报错

springboot连接redis 项目启动
服务器上redis是开着的 也能连上

redis.conf中绑定本地id也删除了

就是用这个连接池的时候报错

控制台报如下错误:

org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:204)
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:348)
    at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:129)
    at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:92)
    at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:79)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:194)
    at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169)
    at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91)
    at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:169)
    at com.how2java.test.TestRedisOne.testRedisOne(TestRedisOne.java:82)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
    Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    at redis.clients.util.Pool.getResource(Pool.java:53)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:16)
    at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:194)
    ... 38 more


Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
    at redis.clients.jedis.Connection.connect(Connection.java:207)
    at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:93)
    at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1767)
    at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:106)
    at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:888)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:432)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:361)
    at redis.clients.util.Pool.getResource(Pool.java:49)
    ... 41 more


Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at redis.clients.jedis.Connection.connect(Connection.java:184)
    ... 48 more


package com.how2java.springboot.web;

import java.util.Date;






import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.how2java.redis.RedisClient;
import com.how2java.springboot.pojo.JsonData;
import com.how2java.springboot.pojo.UserPojo;
import com.how2java.utils.JsonUtils;



@RestController
@RequestMapping("/api/v1/redis")
public class RedisTestController {


    //得到redis封装类
    @Autowired
    private RedisClient redis;

    //添加字符串
    @GetMapping(value="add")
    public Object add(){

        redis.set("username", "xddddddd");
        return JsonData.buildSuccess();

    }

    //通过key值得到value字符串
    @GetMapping(value="get")
    public Object get(){

        String value = redis.get("username");
        return JsonData.buildSuccess(value);

    }

    //将对象通过工具类转成String类型,存入redis中
    @GetMapping(value="save_user")
    public Object saveUser(){
        UserPojo user = new UserPojo(1, "abc", "11", new Date());
        String userStr = JsonUtils.obj2String(user);
        boolean flag = redis.set("base:user:11", userStr);
        return JsonData.buildSuccess(flag);

    }

    //通过key值得到value值,让后将value转为对象
    @GetMapping(value="find_user")
    public Object findUser(){

        String userStr = redis.get("base:user:11");
        UserPojo user = JsonUtils.string2Obj(userStr, UserPojo.class);
        return JsonData.buildSuccess(user);

    }        
}

application.propertites

##REDIS (RedisProperties)
spring.redis.host=39.105.35.139
spring.redis.port=6397
spring.redis.pool.max-idle=200
spring.redis.pool.min-idle=200
spring.redis.pool.max-active=2000
spring.redis.pool.max-wait=1000
spring.redis.timeout=3000
spring.redis.database=0
spring.redis.password=
package com.how2java.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

/**
 * 功能描述:redis工具类
 * 对于redisTpl.opsForValue().set(key, value)进行了一次封装,不然每次都要这样保存值
 * 而封装后只需:new RedisClient().set(key,value);
 */
@Component
public class RedisClient {

    @Autowired
    private StringRedisTemplate redisTpl; //jdbcTemplate    

     // 功能描述:设置key-value到redis中    
    public boolean set(String key ,String value){
        try{
            redisTpl.opsForValue().set(key, value);
            return true;
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }    
    }        

     // 功能描述:通过key获取缓存里面的值
    public String get(String key){
        return redisTpl.opsForValue().get(key);
    }        
}


package com.how2java.utils;

import java.io.IOException;

import org.springframework.util.StringUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 字符串转对象,对象转字符串的工具类
 * 因为StringRedisTemplate的opsForValue()方法需要key,value都需要String类型,所以当value值存入对象的时候
 * 先转成字符串后存入。
 */
public class JsonUtils {

    private static ObjectMapper objectMapper = new ObjectMapper();

    //对象转字符串
    public static <T> String obj2String(T obj){
        if (obj == null){
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //字符串转对象
    public static <T> T string2Obj(String str,Class<T> clazz){
        if (StringUtils.isEmpty(str) || clazz == null){
            return null;
        }
        try {
            return clazz.equals(String.class)? (T) str :objectMapper.readValue(str,clazz);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}


package com.how2java.springboot.pojo;

import java.io.Serializable;

/**
 * 这是后端向前端响应的一个包装类
 * 一般后端向前端传值会有三个属性
 * 1:响应状态
 * 2:如果响应成功,把数据放入
 * 3: 描述,响应成功描述,或者失败的描述
 */
public class JsonData implements Serializable {


    private static final long serialVersionUID = 1L;

    private Integer code; // 状态码 0 表示成功,1表示处理中,-1表示失败
    private Object data; // 数据
    private String msg;// 描述

    public JsonData() {
    }

    public JsonData(Integer code, Object data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    // 成功,只返回成功状态码
    public static JsonData buildSuccess() {
        return new JsonData(0, null, null);
    }

    // 成功,传入状态码和数据
    public static JsonData buildSuccess(Object data) {
        return new JsonData(0, data, null);
    }

    // 失败,传入描述信息
    public static JsonData buildError(String msg) {
        return new JsonData(-1, null, msg);
    }

    // 失败,传入描述信息,状态码
    public static JsonData buildError(String msg, Integer code) {
        return new JsonData(code, null, msg);
    }

    // 成功,传入数据,及描述信息
    public static JsonData buildSuccess(Object data, String msg) {
        return new JsonData(0, data, msg);
    }

    // 成功,传入数据,及状态码
    public static JsonData buildSuccess(Object data, int code) {
        return new JsonData(code, data, null);
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }

    @Override
    public String toString() {
        return "JsonData [code=" + code + ", data=" + data + ", msg=" + msg
                + "]";
    }

    //提供get和set方法,和toString方法
}

package com.how2java.springboot.pojo;

import java.util.Date;



public class UserPojo {
    private int age;

    private String pwd;

    private String phone;

    private Date createTime;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
     public UserPojo() {
            super();
        }

        public UserPojo(int age, String pwd, String phone, Date date) {
            super();
            this.age = age;
            this.pwd = pwd;
            this.phone = phone;
            this.createTime = date;
        }
}


在项目中使用redis做缓存,当运行一段时间后就会出现如下错误:Could not get a resource from the pool,然后在看具体的异常信息就是JedisPool中获取不到jedis对象,也就是说连接池中没有可用的jedis。

自己的第一反应就是把最大链接数(setMaxTotal)调大一些,刚开始设置了100、后来200、在后来2000都不行

然后上网一搜发现大家的回答也都是修改最大连接数,如下demo就是网上一篇博客的解释:

1、产生原因:客户端去redis服务器拿连接(代码描述的是租用对象borrowObject)的时候,池中无可用连接,即池中所有连接被占用,且在等待时候设定的超时时间后还没拿到时,报出此异常。

2、解决办法:调整JedisPoolConfig中maxActive为适合自己系统的阀值。

转自 https://blog.csdn.net/QH_JAVA/article/details/54669973

连接超时,如果是云端的服务器的话;这个会跟平时的虚拟机有待不一样;
1.修改redis.conf文件,将 bind 127.0.0.1这一行注释掉,或是将127.0.0.1修改为0.0.0.0
(redis默认只支持本地连接,修改为0.0.0.0时,这样就可以支持外机连接了)
2.修改redis.conf文件,将protected-mode yes 改为no
(解除保护模式,也是DENIED Redis is running in protected mode because protected mode is enabled问题的解决)
要是云的服务机还需要将服务器安全设置里面打开需要的端口
3.重启redis服务