SpringCloud高可用集群搭建及负载均衡配置实战

代码github地址:https://github.com/tzb1017432592/springcloud-lean

这里是我整个项目,其中包含了三个子模块

我会用eureka-server子模块启动三个注册中心实现注册中心高可用,使用eureka-client子模块启动两个服务提供客户端实现服务提供客户端的高可用,然后在启动一个服务消费者端进行服务消费

然后启动三个gateway 网关服务实现,搭建网关的高可用,最后使用nginx实现网关的负载均衡

整个设计是这样的:

注册中心高可用

现在我们要给注册中心eureka-server配置搭建高可用,实现的原理就是起动两个相同服务名称的注册中心在不同的节点上相互注册(由于我这里条件有限,我只能配置相同ip下不同的端口号起动两个不同的注册中心)

注册中心的配置

我这里是配置在了同一个节点上不同的端口启动三个注册中心

复制代码
server:
  port: 8761

eureka:
  instance:
    #eureka 实例的hostname,可以是hostname,也可以自定义配置hostname
    hostname: eureka-cluster01
    #instance-id:是该实例注册到服务中心的唯一ID,也就是在浏览器中看到的服务名
    #默认是${eureka.instance.ip-address}:${spring.application.name}:${server.port}
    #instance-id: tzb1
    #注册时客户端是否使用自己的IP而不是主机名,默认是false
    prefer-ip-address: false
  client:
    #表示是否将自己注册到Eureka Server,在server端这里应该设置为false,但是为了方便看到效果,这里设置我true
    fetch-registry: false
    #表示是否从Eureka Server获取注册的服务信息,在server端这里应该设置为false,但是为了方便看到效果,这里设置我true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/

spring:
  application:
    name: eureka-cluster
  profiles: pre01

---
server:
  port: 8762

eureka:
  instance:
    #eureka 实例的hostname,可以是hostname,也可以自定义配置hostname
    hostname: eureka-cluster02
    #instance-id:是该实例注册到服务中心的唯一ID,也就是在浏览器中看到的服务名
    #默认是${eureka.instance.ip-address}:${spring.application.name}:${server.port}
    #instance-id: tzb2
    #注册时客户端是否使用自己的IP而不是主机名,默认是false
    prefer-ip-address: false
  client:
    fetch-registry: false
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster03:8763/eureka/

spring:
  application:
    name: eureka-cluster
  profiles: pre02

---
server:
  port: 8763

eureka:
  instance:
    #eureka 实例的hostname,可以是hostname,也可以自定义配置hostname
    hostname: eureka-cluster03
    #instance-id:是该实例注册到服务中心的唯一ID,也就是在浏览器中看到的服务名
    #默认是${eureka.instance.ip-address}:${spring.application.name}:${server.port}
    #instance-id: tzb3
    #注册时客户端是否使用自己的IP而不是主机名,默认是false
    prefer-ip-address: false
  client:
    fetch-registry: false
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/

spring:
  application:
    name: eureka-cluster
  profiles: pre03

hostname可以在C:\Windows\System32\drivers\etc\host中配置

利用profiles启动服务应用不同的配置,依旧不同的profiles使用不同的配置,利用idea配置好启动的主类的profiles:

依据profiles配置,启动三个注册中心,这样注册中心就实现了高可用

提供服务客户端高可用

实现的原理就是在不同的节点上分别启动服务名一样的提供服务客户端,将其注册到集群的注册中心中(由于我这里条件有限,我只能配置相同ip下不同的端口号起动不同的服务提供客户端)
(这里注意了,客户端即使只注册了其中一个注册中心,注册中心集群中所有的注册中心成员都会有一样的注册信息,因为集群中注册中心会进行注册信息的相互拷贝)

提供服务客户端的配置

我这里是配置在了同一个节点上不同的端口起动两个提供服务客户端

复制代码
server:
  port: 8751

eureka:
  client:
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/
spring:
  application:
    name: eureka-client01
  profiles: cl01
---
server:
  port: 8752

eureka:
  client:
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/
spring:
  application:
    name: eureka-client01
  profiles: cl02

我在eureka-client子模块定义了一些接口提供后续服务消费者验证使用

复制代码
@RestController
public class Controller {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ServiceInfoUtil serviceInfoUtil;

    @GetMapping("/client01/hello")
    public String test(){
        List<String> services = discoveryClient.getServices();
        return "服务消费:"+services+",端口号:"+serviceInfoUtil.getPort();
    }

    @GetMapping("/consummer/hello")
    public String consummer(){
        return restTemplate.getForEntity("http://EUREKA-CLIENT01/client01/hello",String.class).getBody();
    }
}

提供一个获取被调用服务的端口工具类

复制代码
@Configuration
public class ServiceInfoUtil implements ApplicationListener<WebServerInitializedEvent> {

    private int serverPort;

    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        this.serverPort = event.getWebServer().getPort();
    }

    public int getPort() {
        return this.serverPort;
    }
}

依据profiles配置,启动两个客户端,这样服务提供客户端就实现了高可用:

服务消费

配置了注册中心与服务提供客户端的高可用,我们知道springcloud会通过ribbon进行负载均衡现在

我们在子模块eureka-client基础上启动一个服务消费者,起名叫eureka-consummer

复制代码
server:
  port: 8753

eureka:
  client:
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/
spring:
  application:
    name: eureka-consummer
  profiles: cl03

配置ribbon与RestTemplate 整合

复制代码
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientApplication {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }
}

根据profiles启动应用:

现在三个eureka-server上的注册服务如图:eureka-cluster01:

eureka-cluster02:

eureka-cluster03:

现在我们调用8753端口eureka-consummer应用的/consummer/hello接口,我这里访问http://localhost:8753/consummer/hello即可

第一次访问,访问到了8751端口的eureka-client01应用:

第二次访问,访问到了8752端口的eureka-client01应用:

服务网关高可用

在gateway子模块中引入依赖

复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

yml配置

复制代码
server:
  port: 8851

eureka:
  client:
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/
spring:
  application:
    name: eureka-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
      - id: eureka-client01
        uri: lb://eureka-client01
        predicates:
        - Path=/client01/**

      - id: eureka-consummer
        uri: lb://eureka-consummer
        predicates:
        - Path=/consummer/**

  profiles: gw01


---
server:
  port: 8852

eureka:
  client:
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/
spring:
  application:
    name: eureka-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: eureka-client01
          uri: lb://eureka-client01
          predicates:
            - Path=/client01/**

        - id: eureka-consummer
          uri: lb://eureka-consummer
          predicates:
            - Path=/consummer/**
  profiles: gw02
---
server:
  port: 8853

eureka:
  client:
    service-url:
      defaultZone: http://eureka-cluster01:8761/eureka/,http://eureka-cluster02:8762/eureka/,http://eureka-cluster03:8763/eureka/
spring:
  application:
    name: eureka-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: eureka-client01
          uri: lb://eureka-client01
          predicates:
            - Path=/client01/**

        - id: eureka-consummer
          uri: lb://eureka-consummer
          predicates:
            - Path=/consummer/**
  profiles: gw03

启动类

复制代码
@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

配置idea的启动配置

分别启动服务,看配置中心的信息,我这里已经启动成功

验证:
分别问: http://localhost:8853/consummer/hellohttp://localhost:8852/consummer/hellohttp://localhost:8853/consummer/hello

nginx配置服务网关负载均衡

下载nginx配置nginx.conf

复制代码
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    upstream gatewayserver{
        server 127.0.0.1:8851 weight=1;
        server 127.0.0.1:8852 weight=1;
        server 127.0.0.1:8853 weight=1;
    }
    
    server {
        listen       80;
        server_name  gateway.cluster;

        location / {
            proxy_pass  http://gatewayserver/;
          }
    }
}

然后配置hostname,在C:\Windows\System32\drivers\etc\host中配置

启动nginx

访问http://gateway.cluster/consummer/hello

这样我们的springcloud的高可用就算完成了
最后编辑于:2025-06-28 11:18:52
© 著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务

喜欢的朋友记得点赞、收藏、关注哦!!!

相关推荐
2501_916007472 小时前
Java界面开发工具有哪些?常用Java GUI开发工具推荐、实战经验与对比分享
android·java·开发语言·ios·小程序·uni-app·iphone
iconball2 小时前
个人用云计算学习笔记 --15. (Linux 系统启动原理、Linux 防火墙管理))
linux·运维·笔记·学习·云计算
dragoooon342 小时前
[Linux基础——Lesson2.Linux的基本指令使用]
linux·运维·服务器
ps酷教程2 小时前
spring-batch深入了解
java·spring·batch
C++chaofan2 小时前
通过Selenium实现网页截图来生成应用封面
java·spring boot·后端·selenium·测试工具·编程·截图
半梦半醒*2 小时前
keepalived部署
运维·服务器·nginx·架构·centos·apache
hweiyu002 小时前
从0手写自己的Linux x86操作系统(视频教程)
linux·运维·数据库
铭哥的编程日记2 小时前
《Linux 基础 IO 完全指南:从文件描述符到缓冲区》
android·linux·运维
渣哥2 小时前
事务嵌套场景必问:Spring 传播机制如何真正发挥作用?
java