网站建设定制开发分为软负载均衡、网站建设定制开发硬负载均衡、DNS负载均衡。
先上一图:
区别看这:
网站建设定制开发是软负载均衡的客户端工具。网站建设定制开发用于客户端的负载均衡。
补充:Nginx网站建设定制开发是软负载均衡的服务器端工具。网站建设定制开发用于服务器端的负载均衡。
Ribbon网站建设定制开发实现负载均衡:
Ribbon是软负载均衡的客户端工具。所以肯定是用在客户端了,即消费者端。注意:消费者端也需要注册进。
使用前提:已经实现通过服务名来访问服务。即已经完成服务注册与服务发现。
代码:
生产者端application.yml代码:
- server:
- port: 8083
-
- spring:
- application:
- name: ProviderCRUD
- datasource:
- druid:
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://127.0.0.1:3306/mybatis_plus_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
- username: root
- password: root
- initial-size: 5
- min-idle: 5
- max-active: 20
- #最大超时时间 ms
- max-wait: 60000
- #设置多长时间进行一次检测 ms
- time-between-eviction-runs-millis: 60000
- #配置一个连接在连接池中最小的生存时间 ms
- min-evictable-idle-time-millis: 300000
- validation-query: select 1 from dual
- test-on-borrow: false
- test-on-return: false
- test-while-idle: false
- #打开PSCache,并指定每个连接上的PSCache大小
- pool-prepared-statements: true
- max-pool-prepared-statement-per-connection-size: 20
- #配置监控拦截器,去掉后监控界面sql无法显示 wall用于防火墙
- filters: stat,slf4j,wall,log4j
- #通过connectProperties属性打开mergeSql功能,可记录慢sql ms
- connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
- #合并多个DruidDataSource的监控记录
- use-global-data-source-stat: true
- type: com.alibaba.druid.pool.DruidDataSource
-
- mybatis-plus:
- configuration:
- log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
-
- eureka:
- client:
- service-url:
- defaultZone: http://127.0.0.1:8082/eureka/,http://127.0.0.1:8084/eureka/,http://127.0.0.1:8085/eureka/
- instance:
- #自定义服务名称
- instance-id: SpringCloudTestSGG-ProviderCRUD1
- #访问路径是否显示IP地址
- prefer-ip-address: true
-
-
-
生产者端controller代码:
- @RestController
- @RequestMapping("/user")
- public class UserController {
-
- @Resource
- private UserMapper userMapper;
- @Resource
- private UserService userService;
- @Autowired
- private DiscoveryClient discoveryClient;
-
- @GetMapping("/getAllUser")
- public String getAllUser(){
- List<User> users = userMapper.selectList(null);
- String jsonString = JSONObject.toJSONString(users);
- return jsonString;
- }
-
-
- //服务发现
- @RequestMapping("/discovery")
- public Object discovery(){
-
- List<String> services = discoveryClient.getServices();
- System.out.println("***********"+services);
-
- List<ServiceInstance> instances = discoveryClient.getInstances("PROVIDERCRUD");
- for (ServiceInstance instance : instances) {
- System.out.println(instance.getHost()+"\t"+instance.getServiceId()+"\t"+instance.getPort()+"\t"+instance.getUri());
- }
- return this.discoveryClient;
- }
- }
生产者端启动类代码:
- @EnableEurekaClient //本服务启动后,自动注册进Eureka
- @SpringBootApplication
- @EnableDiscoveryClient //服务发现
- public class SpringCloudEurekaClient {
- public static void main(String[] args) {
- SpringApplication.run(SpringCloudEurekaClient.class, args);
- }
- }
使用Ribbon负载均衡的时候,生产者启动类上一定要加上@EnableDiscoveryClient 注解,表示服务可以被发现。
既然是负载均衡那肯定不止一个生产者端了,多建几个,都注册进Eureka。
生产者端application.yml中配置代码几乎都是一样的。
主要区别在端口号一定不同,要不然端口冲突,服务启动不起来。
因为每一个服务都可以有自己的数据库,所以数据库方面的配置可能不同。
服务实例名spring.application.name一定是相同的,因为是通过服务名来负载均衡,所以必须保证一样。
在消费者端或者说客户端Maven中引入Ribbon依赖
-
-
- <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-ribbon</artifactId>
- <version>1.4.7.RELEASE</version>
- </dependency>
消费者端application.yml配置相对简单,因为负责请求的转发,调用其他服务,所以不需要向Eureka中注册自己
- server:
- port: 8086
-
- eureka:
- client:
- service-url:
- defaultZone: http://127.0.0.1:8082/eureka/,http://127.0.0.1:8084/eureka/,http://127.0.0.1:8085/eureka/
- #表示不把自己注册到Eureka
- register-with-eureka: false
- instance:
- instance-id: SpringCloudTestSGG-Consumer1
- prefer-ip-address: true
-
-
- spring:
- application:
- name: ConsumerCRUD
消费者端RestTemplate配置代码:
- @Configuration
- public class RestConfig {
-
- @Bean
- @LoadBalanced //负载均衡
- public RestTemplate restTemplate(){
- return new RestTemplate();
- }
- }
RestTemplate配置类中一定要添加@LoadBalanced 负载均衡注解。
消费者端controller代码:
- @RestController
- @RequestMapping("/rest")
- public class UserRestController {
-
- @Resource
- private RestTemplate restTemplate;
-
- //通过服务名来进行访问服务,这里演示用
- //PROVIDERCRUD服务名字
- private static String PREFIX_URL="http://PROVIDERCRUD/user/";
-
- @GetMapping("/getAllUser")
- public String getAllUser(){
- return restTemplate.getForObject(PREFIX_URL+"getAllUser",String.class);
- }
-
- @RequestMapping("/discovery")
- public Object discovery(){
- return restTemplate.getForObject(PREFIX_URL+"discovery",Object.class);
- }
- }
这样就可以简单实现Ribbon的负载均衡了。
Ribbon默认负载均衡的策略是轮询。就是一个一个的轮流访问服务。
下图是Ribbon自带的负载均衡策略。
切换负载均衡策略:Ribbon的IRule接口:
IRule源码:
- /*
- *
- * Copyright 2013 Netflix, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- package com.netflix.loadbalancer;
-
- /**
- * Interface that defines a "Rule" for a LoadBalancer. A Rule can be thought of
- * as a Strategy for loadbalacing. Well known loadbalancing strategies include
- * Round Robin, Response Time based etc.
- *
- * @author stonse
- *
- */
- public interface IRule{
- /*
- * choose one alive server from lb.allServers or
- * lb.upServers according to key
- *
- * @return choosen Server object. NULL is returned if none
- * server is available
- */
-
- public Server choose(Object key);
-
- public void setLoadBalancer(ILoadBalancer lb);
-
- public ILoadBalancer getLoadBalancer();
- }
切换策略代码:
- @Configuration
- public class IRuleConfig {
-
- @Bean
- public IRule iRule(){
-
- /**
- * RoundRobinRule
- * 轮询
- */
- return new RoundRobinRule();
-
-
- /**
- * RandomRule
- * 随机
- */
- return new RandomRule();
-
-
- /**
- * AvailabilityFilteringRule
- * 过滤访问故障和超过访问或并发阈值的服务。在剩下的服务中轮询。
- */
- return new AvailabilityFilteringRule();
-
-
- /**
- * WeightedResponseTimeRule
- * 按照权重访问。权重计算方法:响应时间越快的权重越高,被选中的概率越大。刚启动时如果统计信息不足,先按轮询策略,
- * 后续统计信息足够了再按照权重策略。
- */
- return new WeightedResponseTimeRule();
-
- /**
- * RetryRule
- * 先按照轮询策略访问服务,如果获取服务失败,则会在指定时间内进行重试,重新获取服务。
- */
- return new RetryRule();
-
- /**
- * BestAvailableRule
- * 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
- */
- return new BestAvailableRule();
-
- /**
- * ZoneAvoidanceRule
- * 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
- */
- return new ZoneAvoidanceRule();
- }
- }
实现自定义的Ribbon负载均衡策略:
实现IRule接口:
步骤:在客户端即消费者端启动类上添加
@RibbonClient(name = "xxx",configuration=yyy.class) 注解,
name表示执行此策略的服务名;configuration表示自定义负载策略的类。
简而言之就是针对名为xxx的服务,执行yyy.class中的负载策略。
注意:
也就是说,自定义的负载均策略类不能和启动类在同一个包或者父包下。
消费者启动类:
- @SpringBootApplication
- @EnableEurekaClient
- @RibbonClient(name = "PROVIDERCRUD",configuration= IRuleConfig.class)
- public class SpringCloudConsumer {
- public static void main(String[] args) {
- SpringApplication.run(SpringCloudConsumer.class,args);
- }
- }
MyRuleConfig,自定义负载算法类:
- /**
- * 自定义负载策略
- * 要求:轮询服务,并且每个服务连续五次
- */
-
- public class MySelfIRule extends AbstractLoadBalancerRule {
-
- private Logger log;
- private Integer total = 0;
- private int index = 0;
- public MySelfIRule() {
- System.out.println("执行无参构造方法");
- }
-
- public MySelfIRule(ILoadBalancer lb) {
- this();
- setLoadBalancer(lb);
- System.out.println("执行有参构造方法");
- }
-
- Server server = null;
-
- public Server choose(ILoadBalancer lb,Object key) {
- System.out.println("执行双参数choose查找返回server");
- if (lb==null){
- log.log(Level.WARNING,"没有对应的服务...");
- }
-
- List<Server> allServers = lb.getAllServers();
- if (allServers.size()==0){
- log.log(Level.WARNING,"没有指定的>>>"+lb+"<<<服务");
- return null;
- }
-
- if (total<4){//0,1,2,3,4
- server = allServers.get(index);
- total++;
- }else {//5
- total=0;
- index++;
- if (index>=allServers.size()){
- index=0;
- }
- }
-
- if (server==null){
- return null;
- }
- return server;
- }
-
-
- public Server choose(Object key) {
- System.out.println("执行单参数choose");
- return choose(getLoadBalancer(),key);
- }
-
- public void initWithNiwsConfig(IClientConfig clientConfig) {
- System.out.println("执行初始化方法initWithNiwsConfig,获取服务信息...");
-
- String clientName = clientConfig.getClientName();
- System.out.println("获取服务名>>:"+clientName);
-
- System.out.println("获取配置信息...");
- Map<String, Object> properties = clientConfig.getProperties();
- for (Map.Entry<String, Object> stringObjectEntry : properties.entrySet()) {
- System.out.println(stringObjectEntry);
- }
- }
-
- }
在切换策略代码中,直接切换即可:
- @Configuration
- public class IRuleConfig {
-
- @Bean
- public IRule iRule(){
-
-
- /**
- * 自定义
- */
- return new MySelfIRule();
- }
- }
到此完成自定义的Ribbon负载均衡算法。
Nginx负载均衡待更新。。。