92.【SpringCloud NetFilx】(六)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
EMR Serverless StarRocks,5000CU*H 48000GB*H
简介: 92.【SpringCloud NetFilx】
  1. 修改控制层对服务层的访问路径
  • 使用Ribbon负载均衡,我们这里不应该写死。而应该通过id名(服务提供者),进行获取 SpringCloud-provider-dept
//  设置服务层的前缀为常量
    //private static final String REST_URL_PREFIX="http://localhost:8081";
    // 使用Ribbon负载均衡,我们这里不应该写死。而应该通过id名(服务提供者),进行获取 SpringCloud-provider-dept
    private static final String REST_URL_PREFIX="http://SpringCloud-provider-dept";
package com.jsxs.controller;
import com.jsxs.pojo.Dept;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.List;
@RestController
public class DeptConsumerController {
    //注意: 这里我们只是引入了实体类的数据,并没有引入service接口
    //思考: 消费者界面不应该存在Dao层也不应该存在Service层,该如何使用服务呢
    //RestTemplate  ... 我们直接调用就行,但需要注入到Spring中
    @Resource
    // (URI url, 实体 map,Class<T> responseType) 地址---- 实体 ----返回类型.class
    private RestTemplate restTemplate;   // 提供多种便捷访问远程   访问http服务的方法,简单的Rest
    //  设置服务层的前缀为常量
    //private static final String REST_URL_PREFIX="http://localhost:8081";
    // 使用Ribbon负载均衡,我们这里不应该写死。而应该通过id名(服务提供者),进行获取 SpringCloud-provider-dept
    private static final String REST_URL_PREFIX="http://SpringCloud-provider-dept";
    //  根据id进行数据的查找
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long deptno){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/queryById/"+deptno,Dept.class);
    }
    //  添加数据
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
    }
    //  查找全部数据
    @RequestMapping("/consumer/dept/all")
    public List<Dept> all(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/all",List.class);
    }
}

结论: Eureka和Ribbon整合之后,客户端可以直接调用,不再用关心我们的IP地址和端口号。 为什么? ①因为我们实现了负载均衡,所以客户端像跳哪个服务器,负载均衡会帮助我们寻找。②我们在controller做了手脚,通过注册服务的id进行跳转。

3.使用Ribbon实现负载均衡

流程图:

(Ribbon有两个步骤:1.去Eureka集群中查找可用的服务列表;2.通过负载均衡的算法,从服务提供者中选择一个看起来比较OK的)

1.新建两个服务提供者Moudle:springcloud-provider-dept-8003、springcloud-provider-dept-8002

CREATE DATABASE db03;
USE db03;
CREATE TABLE dept(
  deptno BIGINT(20) Not Null PRIMARY KEY AUTO_INCREMENT,
  dname VARCHAR(60) DEFAULT NULL,
  db_source VARCHAR(60) DEFAULT NULL
);
INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('售后部',DATABASE());

2.参照springcloud-provider-dept-8001 依次为另外两个Moudle添加pom.xml依赖 、resourece下的mybatis和application.yml配置,Java代码

3.启动所有服务测试(根据自身电脑配置决定启动服务的个数),访问http://eureka7001.com:7001/查看结果

4.进行用户访问

第一次刷新

第二次刷新

Eureka

内存

以上这种每次访问http://localhost/consumer/dept/list随机访问集群中某个服务提供者,这种情况叫做轮询,轮询算法在SpringCloud中可以自定义。

4.自定义负载均衡算法

如何切换或者自定义规则呢?

(1).切换系统已有均衡算法

默认的是轮询,如果我们需要切换。那么我们就自己配置一个类

@Bean
    public IRule myIRule(){
        return new RandomRule();
    }

1.在springcloud-provider-dept-80模块下的ConfigBean中进行配置,切换使用不同的规则

package com.jsxs.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration  //  相当于application.xml文件
public class ConfigBean {
    // IRule :
    /**
     *      1.AvailabilityFilteringRule  先过滤掉奔溃(跳匝)的服务,对剩下的服务进行轮询
     *      2.RoundRobinRule  轮询   《默认》
     *      3  .RoundRobinRule 随机
     *      4. RetryRule 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内运行。
     *
     */
    @LoadBalanced   //  配置负载均衡,只需要添加一个注解就可以
    @Bean       //  把RestTemplate注入到Spring中去
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
    // 启用随机作为Ribbon的算法
    @Bean
    public IRule myIRule(){
        return new RandomRule();
    }
}

2.启动测试: 发现真的变成随机负载了。

(2).自定义负载均衡算法

1.切记我们自定义的负载均衡算法,不能被Spring扫描到。所以我们自定义的算法需要放在启动类的上一级

自定义的算法会覆盖默认的算法均衡
FooConfiguration必须是@Configuration,但请注意,它不在主应用程序上下文的@ComponentScan
中,否则将由所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication)
,则需要采取措施避免包含(例如将其放在一个单独的,不重叠的包中,或者指定要在@ComponentScan)。

2.自定义配置的java文件 murule/JsxsRandomRule.java

package com.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class JsxsRandomRule extends AbstractLoadBalancerRule {
    public JsxsRandomRule() {
    }
    @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            Server server = null;
            while(server == null) {
                if (Thread.interrupted()) {
                    return null;
                }
                List<Server> upList = lb.getReachableServers();   // 获得活着的服务
                List<Server> allList = lb.getAllServers();   // 获得全部的服务
                int serverCount = allList.size();      //
                if (serverCount == 0) {
                    return null;
                }
                int index = this.chooseRandomInt(serverCount);   //生成随机数
                server = (Server)upList.get(index);  //从活着的服务中,随机获取一个
                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }
                    server = null;
                    Thread.yield();
                }
            }
            return server;
        }
    }
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }
    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }
    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }
}

3.在启动类上声明注解

package com.jsxs;
import com.myrule.JsxsRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
@EnableEurekaClient
// 在微服务启动的时候,就会加载我们自定义的均衡算法。
@RibbonClient(name = "SpringCloud-provider-dept",configuration = JsxsRule.class)  // 服务端的ID名 自定义配置的类
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}
  1. 切换成我们自定义的负载均衡 myrule/JsxsRule.java
package com.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JsxsRule {
    // 启用随机作为Ribbon的算法
    @Bean
    public IRule myIRule(){
        return new JsxsRandomRule();
    }
}

5.测试无误。

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
5月前
|
消息中间件 NoSQL Java
Spring Cloud项目实战Spring Cloud视频教程 含源码
Spring Cloud项目实战Spring Cloud视频教程 含源码
96 1
|
16天前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
29 0
|
2月前
|
Java Spring
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
|
2月前
|
Java Spring 容器
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
|
2月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
2月前
|
SQL Java 数据库连接
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
|
2月前
|
Java 开发工具 Spring
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
|
2月前
|
NoSQL Java Redis
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
|
2月前
|
Java Spring
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
|
2月前
|
Java Maven Python
【Azure Spring Cloud】部署Azure spring cloud 失败
【Azure Spring Cloud】部署Azure spring cloud 失败