SpringCloud微服务 【实用篇】| Eureka注册中心、Ribbon负载均衡

news2024/9/28 19:17:23

目录

一:Eureka注册中心

1. Eureka原理

2. 动手实践

①搭建EurekaServer

②服务注册

③服务发现 

二:Ribbon负载均衡

1. 负载均衡原理

2. 负载均衡策略

3. 懒加载


一:Eureka注册中心

前面已经分析了,无论是SpringCloud还是SpringCloudAlibaba,两者的注册中心都有Eureka,所以现在就来学习一下Eureka。

Dubbo

SpringCloud

SpringCloudAlibaba

注册中心

zookeeper、Redis

Eureka、Consul

Nacos、Eureka

服务远程调用

Dubbo协议

Feign(http协议)

Dubbo、Feign

配置中心

SpringCloudConfig

SpringCloudConfig、Nacos

服务网关

SpringCloudGateway、Zuul

SpringCloudGateway、Zuul

服务监控和保护

dubbo-admin,功能弱

Hystix

Sentine

1. Eureka原理

服务调用出现的问题

①服务消费者该如何获取服务提供者的地址信息?--------》注册中心

②如果有多个服务提供者,消费者该如何选择?--------》负载均衡

③消费者如何得知服务提供者的健康状态?--------》心跳反应

Eureka的原理

在Eureka的结构当中,分为两个角色:

第一个角色:eureka-server(注册中心)服务端,记录和管理微服务。

第二个角色:user-service(服务提供者)和 order-service(服务消费者);不管是服务者还是消费者都是微服务,所以提供者和消费者统称为Eureka的客户端client

①user-service在启动的那一刻,会把自己的信息注册给eureka;注册中心会记录服务器名称、IP端口等信息。此时如果有人想消费,就不需要自己去记录信息,直接找eureka,拉取服务器信息;这实际上就解决了上述的第一个问题

②例如:此时拿到了3个记录信息,如何选呢?通过负载均衡的知识选出来一个,然后就可以远程调用发请求;这就解决了上述的第二个问题

③那选出来的这个会不会是挂的呢?不会,因为提供者服务每隔30秒都会向eureka发一次心跳,来确认自己的状态;如果检测到不跳了、挂了,eureka就会把它从注册中心的列表中剔除掉,消费者就可以拉取到最新的信息;这就解决了上述的第三个问题

总结:在Eureka架构中,微服务角色有两类

(1)EurekaServer:服务端,注册中心

作用:记录服务信息,进行心跳监控。

(2)EurekaClient:客户端

Provider:服务提供者,例如上述的 user-service

①注册自己的信息到EurekaServer。

②每隔30秒向EurekaServer发送心跳。

Consumer:服务消费者,例如上述的 order-service

①根据服务名称从EurekaServer拉取服务列表。

②基于服务列表做负载均衡,选中一个微服务后发起远程调用。

2. 动手实践

接下来就动手实践:总共分为三个部分:搭建注册中心服务注册服务发现

①搭建EurekaServer

以下搭建信息是基于这篇博客的内容SpringCloud 【实用篇】| 服务拆分及远程调用http://t.csdnimg.cn/pj77E

第一步:创建Maven的独立项目eureka-server引入spring-cloud-starter-netflix-eureka-server的依赖

注:从这里也可以看出实际上Spring已经集成了Erueka,直接引入依赖使用即可!与我们后面学习的Nacos注册中心不同!

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-demo</artifactId>
        <groupId>cn.itcast.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka-server</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <!--引入eureka起步依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>



</project>

第二步:编写启动类,添加@EnableEurekaServer注解,表示自动装配的开关

package cn.itcast.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
// 假如@EnableEurekaServer注解
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

第三步:添加application.yml文件,配置信息

注:为什么还要配置eureka的地址信息,自己配置自己?

答:eureka自己也是一个微服务,在启动时,会将自己也注入到eureka上,为了以后集群之间通信去用,相互做注册进行通信。

#配置端口号
server:
  port: 10086
#eureka的服务器名称
spring:
  application:
    name: eureka-server
#eureka的地址
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

启动eureka,进行访问

此时的注册列表就自己,把自己注册进去了!

②服务注册

user-service服务order-service服务注册到EurekaServer(已user-service为例),步骤如下:

第一步:在项目user-service引入spring-cloud-starter-netflix-eureka-client的依赖

<!--加如eureka的依赖-->
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

第二步:application.yml文件,编写下面的配置:

spring:
  application:
    name: user-service #新加入的eureka服务器的名称
eureka: #新加入的eureka地址
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

启动order-service和user-service,此时的注册列表

此时的注册列表就把order-service和user-service项目注册进去了!

补充:我们可以将user-service多次启动, 模拟多实例部署,但为了避免端口冲突,需要修改端口设置:

此时的eureka页面

此时对于注册进去的user-service启动了两个实列!

③服务发现 

在order-service完成服务拉取:服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡。

第一步:修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口

// 原来是硬编码的方式,写死了
String url = "http://localhost:8081/user/"+order.getUserId();
// 现在使用加入eureka注册中心的服务器名称代替IP和端口号
String url = "http://user-service/user/"+order.getUserId();

第二步:在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解@LoadBalanced

package cn.itcast.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    // 注册RestTemplate
    @Bean
    @LoadBalanced // 加入负载均衡的注解
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

此时重启order-service,连续进行两次访问,此时应该访问UserApplication--->8081还是UserApplication2--->8082呢?

UserApplication日志信息显示:

UserApplication2日志信息显示:

发现两个是轮循方式访问,成功实现了负载均衡,至于负载均衡的原理下面会讲!

总结:

①搭建EurekaServer

引入eureka-server依赖;

启动类上添加@EnableEurekaServer注解;

application.yml中配置eureka端口号、地址、服务器名称

②服务注册

引入eureka-client依赖;

application.yml配置eureka地址、服务器名称

③服务发现

用服务提供者的服务名称(代替端口号和IP)远程调用;

给注入的RestTemplate添加@LoadBalanced注解

二:Ribbon负载均衡

前言:对于高版本的SpringCloud的Ribbon组件已经弃用了被Spring Cloud Loadbalancer替代!

前面我们用EurekaClient(注册中心)实现了服务的拉取和负载均衡,我们只是指定了一个服务器的名称、加了@LoadBalanced注解,一切就自动完成了!那么是什么时候进行的服务拉取?什么时候进行的负载均衡?负载均衡的原理是什么?策略是什么?接下来就学习SpringCloud的第二个组件Ribbon

1. 负载均衡原理

order-service发起请求http://userservice/user/1,实际上这个请求并不是真实可用的地址,在浏览器是无法进行访问,是无法到达后面某个服务的;中间会被Ribbon把请求拦下来进行处理,去找到真实的地址;通过服务器名称userservice找eureka确定真实的地址(IP和Port),拉取服务,然后做负载均衡。

源码分析 

@LoadBalanced注解就相当于一个标记,标记RestTemplate发起的请要被Ribbon拦截

   // 注册RestTemplate
    @Bean
    @LoadBalanced // 假如负载均衡的注解
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

 这个拦截的动作是通过LoadBalancerInterceptor类去完成的

这个类实现了ClientHttpRequestInterceptor接口(客户端Http请求的拦截器);会去拦截由客户端发起的Http请求;而RestTemplate就是发Http请求的客户端。

package org.springframework.cloud.client.loadbalancer;

import java.io.IOException;
import java.net.URI;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
    private LoadBalancerClient loadBalancer;
    private LoadBalancerRequestFactory requestFactory;

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
        this.loadBalancer = loadBalancer;
        this.requestFactory = requestFactory;
    }

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
        this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
    }
    // 重写的Intercept方法
    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
        URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
        return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
    }
}

在重写的intercept方法上打断点

浏览器发送localhost:8080/order/101请求回到断点

拿到地址后,调用getHost方法拿到主机名

拿到服务器名称去找eureka完成服务的拉取;把服务器名称交给loadBalancer去执行,实际上loadBalancer对象就是一个RibbonLoadBalanceClient(负载均衡客户端)

execute方法就是执行的意思,所以要跟进这个方法,会进入RibbonLoadBalanceClient对象的excute方法(一些版本的Jar包会进入接口LoadBalanceClient的excute方法,在其实现类多打一个断点即可)

这个ILoadBalancer对象(实际上是DynamicServerListLoadBalance-动态服务列表负载均衡器)就可以拿到对应的服务(成功被拉取到服务列表)

拉取到服务列表,接下来就是进行负载均衡! 

此时getServer方法又调用了chooseServer方法,又去转到ZoneAwareLoadBalancer类调用父类的chooseServer方法

最终调用到BaseLoadBalancer类的rule类的choose方法

rule类是一个IRule接口,默认的负载均衡规则ZoneAvoidanceRule

这个接口还有其它负载均衡规则的实现类

负载均衡流程

2. 负载均衡策略

上面我们学写了负载均衡的原理,知道IRule接口决定了负载均衡的策略;接下来就分析IRule接口有哪些实现,以及将来如何修改每个实现!

Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口都是一种规则:

 常见的负载均衡策略

内置负载均衡规则类

规则描述

RoundRobinRule

简单轮询服务列表来选择服务器。

AvailabilityFilteringRule

对以下两种服务器进行忽略:

 (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。

(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。

WeightedResponseTimeRule

为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。

ZoneAvoidanceRule

以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。(先分区域,在区域内在轮循

BestAvailableRule

忽略那些短路的服务器,并选择并发数较低的服务器。

RandomRule

随机选择一个可用的服务器。

RetryRule

重试机制的选择逻辑

通过定义IRule实现可以修改负载均衡规则,有两种方式:

第一种方式:在OrderApplication启动类中注册新的Rule-------这是全局的配置

package cn.itcast.order;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    // 注册RestTemplate
    @Bean
    @LoadBalanced // 加入负载均衡的注解
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    // 修改负载均衡的规则---随机
    @Bean
    public IRule randomRule(){
        return new RandomRule();
    }
}

第二种方式:在application.yml文件中修改配置-------针对某个服务进行配置

user-service: # 给某个微服务配置负载均衡规则,微服务的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡规则

3. 懒加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载,clients是一个集合,后面可以配多个
    clients:
     - user-service # 指定对user-service这个服务饥饿加载

Ribbon负载均衡总结

①Ribbon负载均衡规则:规则接口是IRule,默认实现是ZoneAvoidanceRule,根据区域选择服务列表,然后轮询。

②负载均衡自定义方式

代码方式:配置灵活,但修改时需要重新打包发布;

配置方式:直观,方便,无需重新打包发布,但是无法做全局配置;

③饥饿加载:开启饥饿加载,指定饥饿加载的微服务名称。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1235696.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从0开始学习JavaScript--JavaScript中的集合类

JavaScript中的集合类是处理数据的关键&#xff0c;涵盖了数组、Set、Map等多种数据结构。本文将深入研究这些集合类的创建、操作&#xff0c;以及实际应用场景&#xff0c;并通过丰富的示例代码&#xff0c;帮助大家更全面地了解和应用这些概念。 数组&#xff08;Array&…

【Java】NIO概述

本文主要介绍Java的IO。 这里主要按类的操作方式和操作对象对JavaIO进行分类&#xff0c;方便理解&#xff0c;后续使用时可以方便地查询。 一、操作方式分类 首先介绍几组概念&#xff1a; 字节流和字符流&#xff1a; 字节流&#xff1a;以字节为单位&#xff0c;每次次读…

【高级网络程序设计】Week2-3 HTML

一、The Basics 1. HTML&HTML file HTMLMarkup languageHyper Text Markup LanguageHTML fileText file with markup tags.htm/.html extension Create an html file Open an editor Type: <html><head><titile><body> Save it as .html Open i…

计算机网络——网络可靠性及网络出口配置

1. 前言&#xff1a; 学习目标&#xff1a; 1.了解链路聚合的作用 2. 了解ACL的工作原理 3. 了解NAT的工作原理和配置 2. 网络可靠性方案 网络可靠性是指网络在面对各种异常情况或故障时&#xff0c;能够维持正常运行和提供服务的能力。这包括防止网络中断、减小数据丢失的可能…

vue3中使用全局自定义指令和组件自定义指令

这篇文章会教大家如何实现全局自定义指令和组件自定义指令 &#x1f4d3;全局自定义指令和组件自定义指令的区别&#xff0c;除了写法不同和作用不同&#xff0c;其他的包括生命周期的使用方法都是一致的&#xff0c;全局自定义指令在main.ts中注册后整个项目都可以使用&#x…

dvwa-command injection 代码审计(超详细逐行审计)

dvwa-command injection 代码审计 low <?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target $_REQUEST[ ip ];// Determine OS and execute the ping command.if( stristr( php_uname( s ), Windows NT ) ) {// Windows$cmd shell_exec( ping . $target );}…

Parallel Diffusion Models of Operator and Image for Blind Inverse Problems

盲逆问题算子和图像的并行扩散模型 论文链接&#xff1a;https://arxiv.org/abs/2211.10656 项目链接&#xff1a;https://github.com/BlindDPS/blind-dps Abstract 在正向算子已知的情况下(即非盲)&#xff0c;基于扩散模型的逆问题求解器已经展示了最先进的性能。然而&…

linux md5sum计算hash指令

在soc启动&#xff0c;验证镜像签名时&#xff0c;会计算文件的hash值&#xff0c;确保文件未被修改&#xff0c;md5sum可以计算&#xff0c;有256,512位的的其他指令&#xff0c; 如下&#xff0c;计算文件hash值。

@PostConstruct虽好,请勿乱用

1.问题说明 在日常的业务开发中&#xff0c;有时会利用PostConstruct在容器启动时执行一些任务。例如&#xff1a; PostConstruct public void init(){System.out.println("service 初始化..............."); }一般情况这没什么问题&#xff0c;但最近一个同事在做…

Android加固为何重要?很多人不学

为什么要加固&#xff1f; APP加固是对APP代码逻辑的一种保护。原理是将应用文件进行某种形式的转换&#xff0c;包括不限于隐藏&#xff0c;混淆&#xff0c;加密等操作&#xff0c;进一步保护软件的利益不受损坏。总结主要有以下三方面预期效果&#xff1a; 1.防篡改&#x…

django restful framework序列化与反序列化

在前后端分离开发中&#xff0c;对于RESTfulAPI设置&#xff0c;一般需要将查询/更新数据以JSON方式进行返回。 序列化 Model.py from django.db import models class User(models.Model):username models.CharField(verbose_name用户名,max_length10)age models.IntegerF…

RT-Thread JSN-SR04T

JSN-SR0T4-2.0 超声波测距模块可提供 20cm-600cm 的非接触式距离感测功能&#xff0c;测距精度可达高到 2mm&#xff1b;模块包括收发一体的超声波传感器与控制电路组成。产品采用工业级一体化超声波探头设计&#xff0c;防水型&#xff0c;性能稳定&#xff0c;谦容市场上所有…

手搓js轮播图_JavaScript进阶

手搓js轮播图 逻辑解析html结构图片切换方法圆点导航切换效果左右箭头点击切换圆点导航点击切换自动播放&#xff0c;介入暂停 完整代码 逻辑解析 css的样式我就不再进行讲述&#xff0c;如果有需求可以评论区告诉我&#xff0c;我再出一篇文章进行详细讲解 js轮播图最主要的核…

java算法学习索引之字符串问题

一 判断两个字符串是否互为变形词 【题目】给定两个字符串str1和str2&#xff0c;如果str1和str2中出现的字符种类一样且每种字符出现的次数也一样&#xff0c;那么str1与str2互为变形词。请实现函数判断两个字符串是否互为变形词。 public boolean isDeformation(String str1…

SPSS快速聚类

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件请点击此链接下…

React结合antd5实现整个表格编辑

通过react hooks 结合antd的table实现整个表格新增编辑。 引入组件依赖 import React, { useState } from react; import { Table, InputNumber, Button, Space, Input } from antd;定义数据 const originData [{ key: 1, name: 白银会员, value: 0, equity: 0, reward: 0…

全球首款容器计算产品重磅发布,激活上云用云新范式

云布道师 10 月 31 日&#xff0c;杭州云栖大会上&#xff0c;阿里云云原生应用平台负责人丁宇宣布&#xff0c;阿里云容器计算服务 ACS 正式发布&#xff01;ACS 将大幅降低企业和开发者用云门槛&#xff0c;真正将 Serverless 理念大规模落地。 容器计算服务 ACS&#xff0c…

零代码编程:用ChatGPT将SRT字幕文件批量转为Word文本文档

一个文件夹中有多个srt视频字幕文件&#xff0c;srt文件里面有很多时间轴&#xff1a; 现在想将其批量转为word文档&#xff0c;去掉里面与字符无关的时间轴&#xff0c;在ChatGPT中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个批量将SRT字幕文件转为…

jbase仪器接口设计

jbase的计划有借助虚拟M来实现连仪器&#xff0c;之前陆续写了些TCP逻辑&#xff0c;今天终于整理完成了仪器设计。首先用java的cs程序测试TCP的服务和客户端。 javafx的示例加强 package sample;import javafx.application.Application; import javafx.event.EventHandler; …

如何给shopify motion主题的产品系列添加description

一、Description是什么 Description是一种HTML标签类型&#xff0c;通过指定Description的内容&#xff0c;可以帮助搜索引擎以及用户更好的理解当前网页包含的主要了内容。 二、Description有什么作用 1、基本作用&#xff0c;对于网站和网页做一个简单的说明。 2、吸引点击&…