Spring Cloud:概述,服务注册和服务发现,多机部署和负载均衡

发布于:2025-05-12 ⋅ 阅读:(19) ⋅ 点赞:(0)

什么是微服务

        就是将一个大型的应用程序拆分成多而小的独立的服务模块,每个服务模块围绕某个业务功能建立,具有独立的数据库,服务栈,并通过轻量级的通信协议进行交互。

单体架构

        就是将所有的业务和功能都打包在一个jar包中,这就是单体架构。

单体架构的优点:构建简单,部署简单,一个项目包括了多个功能,省去了不同项目交互调用的麻烦,

单体架构的缺点:由于网站用户越来越多,需求也越来越多,功能需求也越来越多,导致后端的压力越来越大,负载越来越高,一个很小的问题,就会引起很大的连锁反应,冗余性太高。

集群和分布式

        集群:是将一个系统部署到多个服务器上,每个服务器都能提供系统的所有服务,多个服务器通过负载均衡调度完成工作,每个服务器称为集群的节点。

        分布式:将一个系统拆分成多个子系统,多个子系统部署到多个服务器上,多个服务器上的子系统协同完成工作。

集群是多个计算机在做相同的事,分布式是多个计算机在不同的事情。

微服务架构

        就是每个服务只负责一种特定的业务功能,每个服务独立构建,测试部署,互不干扰,可用不同的技术栈。

Spring-Cloud

Spring-Cloud就是微服务的一种解决方案

单项依赖

        微服务之间需要做到单项依赖,严禁循环依赖,双向依赖。

DependencyManagement和Dependencies

dependencies

将所依赖的jar直接加入到项目中,子项目也会继承该依赖。

DependencyManagement

只是申明依赖,并没有jar包的引入,如果子项目需要用到相关的依赖,需要自己引入

  <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <java.version>17</java.version>
        <mybatis.version>2.2.0</mybatis.version> <!-- 使用已知的兼容版本 -->
        <mysql.version>8.0.33</mysql.version>
        <spring-cloud.version>2022.0.3</spring-cloud.version>
    </properties>
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version> <!-- 采用最新兼容版本 -->
            </dependency>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter-test</artifactId>
                <version>${mybatis.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在创建子项目的时候,注意pom文件申明项目的依赖和构建插件

简单创建好父子工程

来进行远程调用

根据订单查询订单信息时,根据订单里面的产品Id,获取产品的详细信息

可以采用RestTemplate

RestTemplate 是 Spring 提供的用于 同步 HTTP 请求的客户端工具类,它可以方便地发送 HTTP 请求并接收响应,支持 GET、POST、PUT、DELETE 等多种请求方法

定义RestTemplate

 @Configuration
 public class BeanConfig {
 @Bean
 public RestTemplate restTemplate(){
 return new RestTemplate();
 }
 }
@Slf4j
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;
    
public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        String url = "http://127.0.0.1:9090/product/"+orderInfo.getProductId();
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;

    }
}

测试一下

但是rul是写死的,如果要是修改IP,就得修改代码

注册中心

CPA理论

一致性:CPA理论中的一致性,指的是强一致性,所有节点在同一时间既有相同的数据。

可用性:保证每个请求都有响应。

分区容错性:当出现网络分区后,系统仍然能对外提供服务。

这三个基本需求,不能一次性全部满足,最多只能满足两个,CA或者CP架构。

Eureka

        Eureka是Netflix开发的基于REST的服务发现框架,主要⽤于服务注册,管理,负载均衡和服务故障 转移,是常见的注册中心。

EurekaServer的搭建

        EurekaServer是一个独立的微服务

注意:要引入eureka-server依赖

 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
 </dependency>

构建插件

build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>org.example.eurekaserver.EurekaServerApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

注意在启动类上添加@EnableEurekaServer注解,用来开启eureka注册中心

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class,args);
    }
}

配置文件

server:
  port: 10010
spring:
  application:
    name: eureka-server
eureka:
  instance:
    hostname: localhost
  client:
    fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false
    register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.
    service-url:
      # 设置Eureka Server的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
logging:
  pattern:
    console: '%d{MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n'

启动服务

 在远程调⽤时,从eureka-server拉取product-service的服务信息,url则不会被写死

@Slf4j
@Service
public class OrderService {  
    @Autowired
    private DiscoveryClient discoveryClient;
    
    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        //从Eureka中获取服务列表
        List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
        String uri = instances.get(0).getUri().toString();

        String url = uri+"/product/"+orderInfo.getProductId();
        log.info("远程调用url:{}", url);
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;

    }

负载均衡

 这行代码是获得了第一个服务实例,但是如果有多个服务实例呢?

EurekaServiceInstance instance = (EurekaServiceInstance) instances.get(0);

在创建几个实例后我们发现访问的都是同一台机器,其它的并没有进行访问。

修改代码,使其轮流访问

int index = atomicInteger.getAndIncrement() % instances.size();
    public OrderDetail selectOrderById(Integer orderId){
        OrderDetail orderDetail = orderMapper.selectOrderById(orderId);
//        String url="http://localhost:9090/product/"+orderDetail.getProductId();
//        if (instances == null || instances.isEmpty()) {
//            log.warn("No available instances for product-service");
//            throw new IllegalStateException("No available instances for product-service");
//        }
        List<ServiceInstance> instances= discoveryClient.getInstances("product-service");
        int index=count.getAndIncrement() % instances.size();
        URI uri = instances.get(index).getUri();
        String url=uri+"/product/"+orderDetail.getProductId();
        log.info("url:{}",url);
        ProductDetail productDetail = restTemplate.getForObject(url, ProductDetail.class);
        orderDetail.setProductDetail(productDetail);
        return orderDetail;
    }

 

请求被均衡的分配在了不同的实例上,这就是负载均衡

负载均衡:当服务流量增⼤时,通常会采⽤增加机器的⽅式进⾏扩容,负载均衡就是⽤来在多个机器或者其他资源 中,按照⼀定的规则合理分配负载

SpringCloudLoadBalancer

SpringCloudLoadBalancer这个组件是用来实现客户端的负载均衡

添加 @LoadBalanced 注解

@LoadBalancerClient(name = "product-service",configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

修改IP端⼝号为服务名称

public OrderDetail selectOrderById(Integer orderId){
        OrderDetail orderDetail = orderMapper.selectOrderById(orderId);
        String url="http://product-service/product/"+orderDetail.getProductId();
        log.info("url:{}",url);
        ProductDetail productDetail = restTemplate.getForObject(url, ProductDetail.class);
        orderDetail.setProductDetail(productDetail);
        return orderDetail;
    }

负载均衡策略

        负载均衡策略是一种思想,有轮询和随机选择两种,就是字面意思。

⾃定义负载均衡策略

//负载均衡策略
public class CustomLoadBalancerConfiguration {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

使⽤@LoadBalancerClient或@LoadBalancerClients注解,可以对不同的服务提供⽅配置不同的客⼾端负载均衡算法策略

name:对哪个服务生效

configuration:在这写负载均衡策略,用哪个负载均衡策略实现

 

希望能对大家有所帮助!!!! 


网站公告

今日签到

点亮在社区的每一天
去签到