一、需要工具
1)nginx
2)JMeter
二、dockers安装Nginx
1. docker pull nginx:stable-perl
2. docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-d nginx:stable-perl
3. #目的:复制出内部的配置文件
docker container cp nginx:/etc/nginx .
4. docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:stable-perl
三、配置Nginx
在nginx.conf中加入如下配置:
1.png
upstream tomcat{
server win10的IP:8080 weight=10;
server win10的IP:8081 weight=10;
server win10的IP:8082 weight=10;
}
在config.d目录下修改default.conf
location / {
# root /usr/share/nginx/html;
# index index.html index.htm;
proxy_pass http://tomcat;
}
2.png
四、创建一个springboot应用引入redisson的依赖
1)加入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zhan</groupId>
<artifactId>sync-in-detail</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SyncInDetail</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.11.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2)创建redisson.yml文件配置相关属性
可参考redisss官网
#Redisson配置
singleServerConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: null
subscriptionsPerConnection: 5
clientName: null
address: "redis://192.168.1.101:6379"
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 32
connectionPoolSize: 64
database: 0
#在最新版本中dns的检查操作会直接报错 所以直接注释掉
#dnsMonitoring: false
dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
"transportMode": "NIO"
==注:这里有个坑,就是左后一行需要在冒号后加一个空格==
五、编写测试代码
package com.zhan.syncindetail.service;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
/**
* @author zhan
* @since 2020-04-27 15:26
*/
@Service
public class RedissonService {
@Autowired
private RedissonClient redissonClient;
@Autowired
private StringRedisTemplate redisTemplate;
public void tryLockOnce() {
String key = "lock_";
//1. 获取锁
RLock lock = redissonClient.getLock(key);
try {
//加锁,此处使用和java的ReentrantLock类似
lock.lock();
//2.执行业务逻辑
String num = redisTemplate.opsForValue().get("num");
Integer i = Integer.parseInt(num);
i = i + 1;
redisTemplate.opsForValue().set("num",i.toString());
} finally {
//3.释放锁
lock.unlock();
System.out.println("-----------------释放锁OK==>"+Thread.currentThread().getName());
}
}
}
配置redisson
package com.zhan.syncindetail.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
/**
* @author zhan
* @since 2020-04-27 14:30
*/
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() throws IOException {
Config config = Config.fromYAML(new ClassPathResource("redisson.yml").getInputStream());
return Redisson.create(config);
}
}
编写测试接口
package com.zhan.syncindetail.controller;
import com.zhan.syncindetail.service.RedissonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author zhan
* @since 2020-04-27 15:24
*/
@RestController
public class RedissonController {
@Autowired
private RedissonService redissonService;
@RequestMapping("incr")
@ResponseBody
public String incr() {
redissonService.tryLockOnce();
return "controller测试ok";
}
}
打包放置左面空文件夹中使用cmd命令同时启动多个窗口分别输入命令:
java -jar sync-in-detail-0.0.1-SNAPSHOT.jar
java -jar sync-in-detail-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar sync-in-detail-0.0.1-SNAPSHOT.jar --server.port=8081
六、启动JMeter
3.png 4.png点击执行可查看执行结果:如下
5.png
结果树报告
7.png
查看redis中执行结果正确值=10000
6.png
总结:完美解决分布式下多线程竞争资源问题。
网友评论