Spring-cloud 主键loadbalance
一,引入
书接上文,如果有多个服务端,那么url( String url="http://127.0.0.1:9090/product/" +orderInfo.getProductId();)就不可写死,我们按照⼀定的规则合理分配负载.
首先创建两个product-Service实例:


手动简单实现负载均衡:
实现启动多个product-Service实例,并访问注册中心

想要轮流访问这三个实例,可以获得product-Service 的列表,然后设置一个变量,这个下标等于[变量=变量%列表的长度],通过这个变量的值作为访问列表的下标值,这样就可以将每个列表里的实例进行轮询
因此在此基础上要对代码进行一定的修改:
首先设置一个全局变量,这个变量是AtomicInteger类型的,它主要提供了原子操作的整数,然后修改内部代码逻辑,然后把获得product-Service实例列表的操作也单独从领出来,这样我们又不用每次调用实例的时候都重新获得一次实例列表(每次读取到的列表中的实例顺序是不一致的).通过单领出来这样的操作,就可以保证读取的就是同一张列表
package com.ABdolphin.order.service;@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;//计数器private AtomicInteger count =new AtomicInteger(1);private List<ServiceInstance> instances;@PostConstructpublic void init(){instances = discoveryClient.getInstances("product-service");}//实现负载均衡public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);//计算轮流的实例indexint index=count.getAndIncrement() % instances.size();//get()+1//获得实例String uri = instances.get(index).getUri().toString();//拼接urlString url=uri+"/product/"+orderInfo.getProductId();log.info("url={}",url);ProduceInfo produceInfo = restTemplate.getForObject(url, ProduceInfo.class);orderInfo.setProduceInfo(produceInfo);return orderInfo;}}
二,负载均衡 loadbalance
客户端负载均衡:

服务端负载均衡:nginx

LoadBalance使用
①添加注解@LoadBalanced
②修改远程调用代码,把ip和端口号改成应用名称
package com.ABdolphin.order.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}
public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);String url="http://product-service/product/"+orderInfo.getProductId();ProduceInfo produceInfo = restTemplate.getForObject(url, ProduceInfo.class);orderInfo.setProduceInfo(produceInfo);return orderInfo;}
结果展示:

负载均衡策略
按照什么样的规则进行负载均衡,一般分为两种策略,一种是轮询策略,一种是随机选择。loadbalance默认使用是轮询,如果想要使用另一种策略呢?
(1) 定义随机算法对象,通过@Bean将其加载到Spring容器中
要求:
①不可以使用@Configuration
②在组件扫描范围之内
package com.ABdolphin.order.config;import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;public class CustomLoadBalancerConfiguration {@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);}
}
(2) 使⽤ @LoadBalancerClient 或者 @LoadBalancerClients 注解
1. name: 该负载均衡策略对哪个服务⽣效(服务提供⽅)
2. configuration : 该负载均衡策略用哪个负载均衡策略实现
@LoadBalancerClient(name = "product-service", configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}
三,在linux上进行部署
(1)构建数据库
首先在linux系统上建设数据库,(构建数据库的语句在我之前的文章,创建工程里面:https://mp.csdn.net/mp_blog/creation/editor/147758673
https://mp.csdn.net/mp_blog/creation/editor/147758673)
(2)修改代码,准备打包
a. 更改pom文件
其中定义了两个profile:dev和prod。每个profile都定义了一个属性profile.name,分别为dev和prod。这个配置通常用于在构建时根据不同的环境激活不同的配置。例如,我们可能会在资源过滤中使用这个属性来加载不同的配置文件。
<profiles><profile><id>dev</id><properties><profile.name>dev</profile.name></properties></profile><profile><id>prod</id><properties><profile.name>prod</profile.name></properties></profile></profiles>
b,复制两个application.yml文件,一个为总文件,一个是dev环境中的,一个是prod环境中的。product-Service和order-Service都需要进行修改

application-dev.yml文件内容保持不变,在application-prod.yml修改数据库的密码,在application.yml修改代码如下显示:
spring:profiles:active: @profile.name@
(3) 打包
选择要打包的配置

挨个进行打包即可:

(4)linux上的操作
在linux上创建一个文件来放置这三个jar包,并创建一个logs包,来放置日志文件
mkdir spring_cloud
cd spring_cloud/
mkdir logs

nohup java -jar eureka-service.jar >logs/eureka.log &
nohup java -jar order-service.jar >logs/order.log &
nohup java -jar product-service.jar >logs/product.log &
java -jar product-service.jar --server.port=9091>logs/product-9091.log &
java -jar product-service.jar --server.port=9092>logs/product-9092.log &
如果端口被占用:
# 1. 检查端口占用 netstat -tulpn | grep :8080# 输出示例: # tcp6 0 0 :::8080 :::* LISTEN 1234/java# 2. 杀死进程(PID 为 1234) sudo kill -9 1234
