Nginx反向代理实现多服务器负载均衡
配置nginx.conf
#负载均衡
upstream lagouServer{
# 用server定义 HTTP地址
server 192.168.52.100:8081;
server 192.168.52.100:8082;
}
server {
listen 80;
server_name www.lagouNB.com;
location / {
# 利用 proxy_ pass可以将请求代理到upstream命名的HTTP服务
proxy_pass http://lagouServer; #转发的地址
index index.html index.htm;
}
}
端口为80,访问Nginx所在服务器地址即可负载均衡到每一台Tomcat服务器
Zookeeper
原理: 其实就是Zookeeper上面有树状分支节点,我们可以创建很多的客户端,然后让指定客户端监听(zookeeper帮忙监听)某个节点,之后该节点发生变化(节点值改变、增加子节点。删除节点),则监听该节点的客户端就会收到信息并且执行process方法,Java中该方法在创建zookeeper客户端时执行一次,之后监听到节点变化都会执行
作用:
- 统一命名服务
- 统一配置管理
- 服务器节点动态上下线(美团外卖)
- 软负载均衡
美团外卖:通过监控临时节点的变化
zoo.cfg配置多台服务器负载均衡(用于监听处理节点)
#######################cluster##########################
server.1=192.168.204.141:2888:3888
server.2=192.168.204.142:2888:3888
server.3=192.168.204.143:2888:3888
传统锁与分布式锁的区别
1.传统锁就是1000个线程抢占一个方法执行,被一个抢到后剩下999个就等待下一次轰抢(无序)
2.分布式锁就是有序排队,每个人都有一个编号,只有编号最小是下一次执行者
分布式锁-商品秒杀(解决高并发问题):
- 所有请求进来,在/lock下创建 临时顺序节点 ,放心,zookeeper会帮你编号排序
- 判断自己是不是/lock下最小的节点
- 是,获得锁(创建节点)
- 否,对前面小我一级的节点进行监听
- 获得锁请求,处理完业务逻辑,释放锁(删除节点),后一个节点得到通知(比你年轻的死了,你
成为最嫩的了) - 重复步骤2
使用方法:
使用apahce提供的zookeeper客户端Curator
- 配置Curator依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version> <!-- 网友投票最牛逼版本 -->
</dependency>
- 在控制层中加入分布式锁的逻辑代码
@Controller
public class ProductAction {
@Autowired
private ProductService productService;
private static String connectString = "192.168.204.141:2181,192.168.204.142:2181,192.168.204.143:2181";
@GetMapping("/product/reduce")
@ResponseBody
public Object reduce( int id) throws Exception {
// 重试策略 (1000毫秒试1次,最多试3次)
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
//1.创建curator工具对象
CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, retryPolicy);
client.start();
//2.根据工具对象创建“内部互斥锁”
InterProcessMutex lock = new InterProcessMutex(client, "/product_"+id);
try {
//3.加锁
lock.acquire();
productService.reduceStock(id);
}catch(Exception e){
if(e instanceof RuntimeException){
throw e;
}
}finally{
//4.释放锁
lock.release();
}
return "ok";
}
}
Dubbo+Zookeeper的RPC分布式架构
调用关系
1.服务容器负责启动,加载,运行服务提供者;
2.服务提供者在启动时,向注册中心注册自己提供的服务;
3.服务消费者在启动时,向注册中心订阅自己所需的服务;
4.在注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给
消费者;
5.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,
再选另一台调用;
6.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中
心;
使用依赖(严格按照)
<packaging>war</packaging>
<properties>
<spring.version>5.0.6.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!--dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.7</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.11.0.GA</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven </groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8001</port>
<path>/</path>
</configuration>
<executions>
<execution>
<!-- 打包完成后,运行服务 -->
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Spring配置
<!--1.服务提供方在zookeeper中的“别名”-->
<dubbo:application name="dubbo-server"/>
<!--2.注册中心的地址-->
<dubbo:registry address="zookeeper://192.168.204.141:2181"/>
<!--3.扫描类(将什么包下的类作为服务提供类)-->
<dubbo:annotation package="service.impl"/>
<!-- 让监控 去注册中心 自动找服务 -->
<dubbo:monitor protocol="registry"/>
<!--设置超时时间为2秒,默认为1秒-->
<dubbo:provider timeout="2000" port="20881"/>
<!-- <dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl01" version="1.0.0"/>-->
<dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl02" version="2.0.0"/>
常用配置说明
- 启动时检查
- 超时时间
- 重试次数
- 多版本
- 本地存根
- 负载均衡策略(测试方法:直接修改Tomcat和provider端口号启动。因为都注册在同一个Zookeeper)
- 高可用(zookeeper宕机)
- 服务降级(是防止分布式服务发生雪崩效应)
注意和理解:
服务者中的@Service为import com.alibaba.dubbo.config.annotation.Service;通过spring配置注册到zookeeper
消费者通过@Reference(远程去服务方将service的实现类注入进来)和zookeeper调用到服务者中的实现类方法
分布式即开发中把查询,修改等service层功能模块部署到不同的服务器上面,然后通过这种方式进行远程调用,缓解单个服务器压力