avatar

SLHAF's blog

SLHAF的个人博客

  • 首页
  • 分类
  • 标签
  • 归档
  • 友链
主页 day_0 分布式入门: 基本知识+Nacos基础
文章

day_0 分布式入门: 基本知识+Nacos基础

发表于 29天前 更新于 28天前
作者 slhaf
51~66 分钟 阅读

前言

现在大二下都已经结束了,之前Java学完基础的Spring Boot也就没再往下学,硬是把自己的智能体项目往下推进了两个月。现在暑假还挺长,是时候补补微服务相关的东西。

虽说网上都说今年是“智能体元年”,各种智能体应用也都层出不穷,但它们很多都还是集中在“加个prompt、微调一下、接入RAG”这些操作上。这两年虽然也有Manus、Open Hands、MiniMax等这类ReAct智能体,但好像也都还处在起步阶段,token费用、模型理解力、长期记忆的稳定性、Prompt遵循程度也确实还需要进一步发展才能支撑其大规模商业化吧🤔。

不过从这些智能体应用的发展趋势来看,这两年“大模型应用工程”说不准还真能成为一个新的行业风口。

不管怎么说吧,后端+Agent相关技术栈,或许还真是一条路,而且这条路自己也倒感兴趣。

分布式基础

这次是跟着尚硅谷的七小时快速通关课程学的,接下来的学习目前来说并不打算跟着教学课程做他们的完整教学项目,而是想着补充好Spring Cloud知识后,去读一些开源项目源码,了解它们的思路、架构、技术,然后围绕自己的智能体项目做一些扩展与适配,毕竟可操作空间挺多的。这条路也没走过,但应该可行。

常见方案

image-20250709211421827.png

架构演进

image-20250709211414788.png

单体

image-20250709211411379.png

  • 优点: 开发部署简便

  • 缺点: 无法应对高并发

集群

image-20250709211406501.png

  • 优点: 解决大并发
  • 缺点: 模块化升级不便、多语言协作不便

分布式

image-20250709211400204.png

image-20250709211353810.png

将一个大型应用拆分成很多小应用分布部署在各个机器。

  • RPC 远程调用
  • 服务熔断
  • 服务雪崩
  • 负载均衡
  • 单点故障
  • 分布式事务

基础项目创建

项目工程结构

image-20250709211348076.png

依赖配置

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring-cloud.version>2023.0.3</spring-cloud.version>
    <spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version>
	<java.version>17</java.version>
</properties>

Nacos

安装

平常用的系统也都是Manjaro了,安装也就不跟着教程来,上docker吧,方便一些。

#!/bin/bash
docker run --name nacos-standalone-derby \
          -e MODE=standalone \
          -e NACOS_AUTH_TOKEN=RhU59ICF0TbzX1O4ppm3h338IccghQrdiRCdmfafGghfvb8W \
          -e NACOS_AUTH_IDENTITY_KEY=slhaf_nacos \
          -e NACOS_AUTH_IDENTITY_VALUE=nacos \
          -p 8080:8080 \
          -p 8848:8848 \
          -p 9848:9848 \
          -d nacos/nacos-server:latest

在项目中引入Nacos发现依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

在需要被发现的服务(Spring Boot项目)中配置Nacos地址和服务名称:

spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.application.name=service-product

功能

注册中心

服务注册

引入Nacos依赖,在项目中做好Nacos服务配置后,启动项目,可以在Nacos中看到新启动的服务

服务发现与远程调用

注解: @EnableDiscoveryClient 开启服务发现,但现在不加这个注解也能正常发现服务。

image-20250709211338404.png

链接: https://cloud.spring.io/spring-cloud-commons/1.3.x/multi/multi__spring_cloud_commons_common_abstractions.html?utm_source=chatgpt.com

开启服务发现后,通过类DiscoveryClient或NacosServiceDiscovery可以发现远程服务,进而获取它们的IP、端口进行不同服务间的通信。

示例:

@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private NacosServiceDiscovery nacosServiceDiscovery;

@Test
void discoveryClientTest() {
    for (String service : discoveryClient.getServices()) {
        System.out.println("service: " + service);
        discoveryClient.getInstances(service).forEach(instance -> {
            System.out.println("IP & PORT -> "+ instance.getHost() + ":" + instance.getPort());
        });
    }
}

@Test
void nacosServiceDiscoveryTest() throws Exception {
    for (String service : nacosServiceDiscovery.getServices()) {
        System.out.println("service: "+service);
        nacosServiceDiscovery.getInstances(service).forEach(instance -> {
            System.out.println("IP & PORT -> "+ instance.getHost() + ":" + instance.getPort());
        });
    }
}
负载均衡

依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

在Spring中提供了一个RestTemplate可以用于发起 网络请求、接受响应并转化为对应的实体类。使用如下:

@Test
void test() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getForObject("http://127.0.0.1:9000/product/1", String.class);
}

实现1

loadbalancer依赖也为其提供了@LoadBalanced注解,配合RestTemplate`的Bean Configuration可以更方便地实现负载均衡。

开启负载均衡以及允许通过依赖注入获取实例:

@Configuration
public class ProductConfiguration {

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

通过RestTemplate发起请求,此时请求的URL中ip地址可以直接填为服务名称:

@Autowired
RestTemplate restTemplate;
@Test
void test() {
    String res = restTemplate.getForObject("http://service-product/product", String.class);
    System.out.println(res);
}

结果:

image-20250709211325932.png

实现2

除了借助@LoadBalanced注解外,也可以通过LoadBalancerClient类选出实例,然后发送请求:

@Autowired
private LoadBalancerClient loadBalancerClient;

@Test
void test2() {
    RestTemplate restTemplate = new RestTemplate();
    ServiceInstance choose = loadBalancerClient.choose("service-product");
    String forObject = restTemplate.getForObject(getUrl(choose), String.class);
    System.out.println(forObject);
}

private String getUrl(ServiceInstance choose) {
    return "http://"+choose.getHost()+":"+choose.getPort()+"/product";
}

但此时使用的restTemplate不能同时开启@LoadBalanced注册,否则会提示No instances available

单例安全原因

看视频时,老师提到RestTemplate是‘线程安全的’,于是我就想着应该是这个类发送请求的流程中没有用到共享的变量,然后顺着走下去可以看到在整条调用链以及整条调用链末尾的doExecute方法中都没有涉及到共享的变量。

配置中心

依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

引入依赖后,必须配置spring.config.import相关内容,或者关闭import检查,否则会出现如下报错:

image-20250709211318572.png

基本用法

通过在配置文件中进行类似相关配置,可以使得项目在启动时从远程Nacos配置中心获取相应的配置文件

spring:
  config:
    import:
      - nacos:common.properties
      - nacos:database.properties

此时在远程修改Nacos配置,项目可以收到对应的事件推送,并对配置进行动态更新

配置可以通过@Value和@RefreshScope注解进行刷新,前者可以获取配置文件中的属性,后者为注解所在的Bean开启动态刷新功能。

@RestController
@Slf4j
@RefreshScope
public class ProductController {

    @Value("${timeout}")
    private String timeout;

    @GetMapping("/product")
    public String getProduct(){
        return timeout;
    }
}

也可以通过@ConfigurationProperties来动态注入,此时不再需要@RefreshScope注解

@Data
@Component
@ConfigurationProperties(prefix = "order")
public class OrderProperties {
    private String db;
    private String timeout;
    private String autoConfirm;
}
@RestController
public class OrderController {

    @Autowired
    private OrderProperties orderProperties;

    @GetMapping("/order")
    public String getOrder(){
        return orderProperties.toString();
    }
}
配置监听

通过NacosConfigManager可以监听配置变化

@EnableConfigurationProperties
@SpringBootApplication
@Slf4j
public class ProductMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductMainApplication.class, args);
    }
    @Bean
    ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager) {
        return args -> {
            nacosConfigManager.getConfigService().addListener("service-product.properties", "DEFAULT_GROUP", new Listener() {
                @Override
                public Executor getExecutor() {
                    return Executors.newFixedThreadPool(4);
                }
                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("receiveConfigInfo: {}", configInfo);
                }
            });
        };
    }
}

nacosConfigManager.getConfigService().addListener可以指定dataId、group,以及一个监听器。

在监听器中可以指定监听所用的线程池和收到推送事件后触发的操作,不过这里的线程池应该使用虚拟线程池更合适些吧。

配置切换

在Nacos中可以为不同的服务以及服务的不同环境配置namespace和group,并在配置文件中进行指定,达到配置文件的动态切换

示例如下:

server:
  port: 9100
  
spring:
  profiles:
    active: test
  application:
    name: server-order
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        namespace: ${spring.profiles.active}
        group: order
---
spring:
  config:
    import:
      - nacos:common.properties
      - nacos:database.properties
    activate:
      on-profile: dev
---
spring:
  config:
    import:
      - nacos:common.properties
      - nacos:database.properties
    activate:
      on-profile: test
Nacos, 后端
学习 分布式 Java
许可协议:  CC BY 4.0
分享

相关文章

7月 9, 2025

day_0 分布式入门: 基本知识+Nacos基础

作者回顾了大二学习经历,计划暑假补充微服务知识,认为大模型应用工程可能成为新风口。文章重点介绍了分布式系统基础概念,包括单体、集群和分布式架构的优缺点,并详细讲解了Nacos的安装与功能,如服务注册、发现、远程调用和负载均衡的实现方法,涉及相关代码配置和依赖管理。

下一篇

简单的ddns解析ipv6 实现思路(包括systemd服务、ddns脚本)

上一篇

day_1 分布式入门: OpenFeign

最近更新

  • 为无头服务器配置带 GUI 的 Clash 客户端:基于 Xvfb + VNC 的解决方案
  • Manjaro/X11 环境下通过 bbswitch 关闭 NVIDIA 显卡以延长续航
  • 关于Bottles中同一容器内不同应用需要配置不同显卡方案的解决办法
  • day_3 分布式入门: Gateway
  • day_2 分布式入门: Sentinel

热门标签

Java 日常 分布式 Linux 学习 脚本 智能体 香橙派

目录

©2025 SLHAF's blog. 保留部分权利。

使用 Halo 主题 Chirpy