当前位置: 首页 > news >正文

spring Cloud笔记--服务治理Eureka

服务治理:Eureka

服务治理

主要用来实现各个微服务实例的自动化注册与发现

  • 服务注册:
    • 服务治理框架中,通常会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号,版本号,通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。
    • 服务注册中心需要以心跳的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,达到排除故障服务的效果。
  • 服务发现:服务间的调用通过服务名发起请求调用实现。注册中心会将服务的位置清单返回给请求方,当请求方要发起调用的时候,从该清单中以某种轮询策略取出一个位置来进行服务调用。

Netflix Eureka

使用Netflix eureka实现服务注册与发现,包含服务端组件,客户端组件,主要适用于通过java实现的分布式系统。

  • Eureka服务端(服务注册中心):支持高可用配置,如果以集群模式部署,当集群中有分片出现故障时,eureka转入自我保护模式。允许在分片故障期间继续提供服务的发现和注册。当故障分片恢复运行时,集群中的其他分片会把他们的状态再次同步回来。
  • Eureka客户端:主要处理服务的注册和发现。通过注解和参数配置的方式嵌入在客户端程序代码中,在应用程序运行时,客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。也能从服务端查询当前注册的服务信息并把他们缓存到本地周期性的刷新服务状态。

搭建服务注册中心

  • @EnableEurekaServer注解:启动一个服务注册中心提供给其他应用进行对话

  • 该服务注册中心也会将自己作为客户端来尝试注册自己,要禁用它的客户端注册行为(配置文件)

    • eureka.client.register-with-eureka:false代表不向注册中心注册自己
    • eureka.client.fetch-registry:注册中心不需要去检索服务,设置为false

注册服务提供者

  • 注入DiscoveryClient对象
  • @EnableDiscoveryClient注解,激活Eureka中DiscoveryClient实现
  • 配置文件中,spring.application.name属性为服务命名
  • 配置文件,eureka.client.serviceUrl.defaultZone属性来指定服务注册中心的地址

高可用注册中心

  • Eureka高可用实际就是将自己作为服务向其他服务注册中心注册自己,这样形成了一组互相注册的服务注册中心,实现服务清单的互相同步,达到高可用效果。
  • 不想使用主机名来定义注册中心的地址,也可以使用ip地址的形式,但需要在配置文件中增加配置参数,eureka.instance.prefer-ip-address=true 该值默认为false

服务发现与消费

消费者:发现服务和消费服务

  • 服务发现的任务由Eureka客户端完成
  • 服务消费的任务由Ribbon完成
    • Ribbon基于HTTP和TCP的客户端负载均衡器,可以通过客户端中配置的ribbonServerList服务端列表去轮询访问达到均衡负载的作用
    • Ribbon与Eureka联合使用时,Ribbon的服务实例清单RibbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心获取服务端列表。
    • 使用NIWSDiscoveryPing来取代IPing,将职责委托给Eureka来确定服务端是否已经启动。

Eureka详解

核心角色:服务注册中心,服务提供者,服务消费者

基础架构

核心三要素

  • 服务注册中心
  • 服务提供者
  • 服务消费者

服务治理机制

例如:

  • 服务注册中心1,和服务注册中心2,互相注册组成了高可用集群
  • 服务提供者启动了两个实例,一个注册到服务注册中心1上,另一个注册到服务注册中心2上
  • 还有两个服务消费者,他们都分别只指向了一个注册中心

重要通信行为

  • 服务提供者

    • 服务注册

      • 服务提供者在启动的时候会通过发送rest请求将自己注册到eureka server,同时带些元数据信息
      • server接到请求后,将元数据信息存储在一个双层结构map中
        • 第一层key是服务名,第二层key是具体服务实例名
      • 注册配置:eureka.client.register-with-eureka=true
    • 服务同步

      • 信息被两个注册中心维护
      • 由于服务注册中心之间因为互相注册为服务,当服务提供者发送注册请求到一个服务注册中心,会将请求转发给集群中相连的其他注册中心,从而实现注册中心之间的服务同步
    • 服务续约

      • 注册完服务之后,服务提供者会维护一个心跳用来持续告诉Eureka server还活着,以防剔除任务将该服务实例从服务列表中排除出去,称为服务续约

      • //用于定义服务续约任务的调用间隔时间,默认30s
        eureka.instance.lease-renewal-interval-in-seconds=30
        //用于定义服务失效时间,默认90s
        eureka.instance.lease-expiration-duration-in-seconds=90
        
  • 服务消费者

    • 获取服务
      • 此时,服务中心已经注册了一个服务,该服务有两个实例
      • 启动服务消费者,他会发送一个rest请求给服务注册中心获取注册的服务清单
      • eureka会维护一份只读的服务清单来返回给客户端,同时该缓存清单会每隔30秒更新一次
      • 获取服务配置:eureka.client.fetch-registry=true
      • 修改缓存清单更新时间:eureka.client.registry-fetch-interval-seconds=30
    • 服务调用
      • 服务消费者通过服务名获得具体提供服务的实例名和该实例的元数据信息
      • 在Ribbon中默认采用轮询的方式进行调用,实现客户端的负载均衡
      • 一个region中可以包含多个zone,每个服务客户端需被注册到一个zone中,每个客户端对应一个region和一个zone
      • 服务调用时,优先访问同处一个zone的服务提供方,若访问不到就访问其他的zone
    • 服务下线
      • 当服务实例进行正常关闭操作时,会触发一个服务下线rest请求给eureka server,告诉服务注册中心
      • 服务端收到请求后,将改服务状态置为下线down,并把该下线事件传播出去。
  • 服务注册中心

    • 失效剔除
      • 服务非正常下线时,服务注册中心并未收到服务下线请求,需要从服务列表中将这些实例剔除
      • 在启动时创建一个定时任务,默认每隔一段时间将当前清单中超时没续约的服务剔除
    • 自我保护
      • eureka server在运行期间,会统计心跳失败的比例在15min之内是否低于85%,如果出现低于的情况,eureka server会将当前的实例注册信息保护起来,让这些实例不会过期,尽可能保护这些注册信息。
      • eureka.server.enable-self.preservation=false参数来关闭保护机制,已确保注册中心可以将不可用的实例正确剔除

源码分析

将普通的springboot应用注册到eureka server或是从eureka server中获取服务列表时,主要做两件事

  • 在应用主类中配置了@EnableDiscoveryClient注解

    • 主要用来开启DiscoveryClient实例

    • @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @Import({EnableDiscoveryClientImportSelector.class})
      public @interface EnableDiscoveryClient {boolean autoRegister() default true;
      }
      
    • DiscoveryClient相关接口,DiscoveryClient,EurekaDiscoveryClient,EurekaClient,LookupService

      • DiscoveryClient:springcloud接口,定义了用来发现服务的常用抽象方法,通过该接口可以有效地屏蔽服务治理的实现细节,可以方便的切换不同服务治理框架
      • EurekaDiscoveryClient:实现的是对Eureka发现服务的封装,所以依赖了EurekaClient接口,
      • EurekaClient:继承了LookupService接口,主要定义了针对Eureka发现服务的抽象方法,而真正实现发现服务的是DiscoveryClient类。
    • DiscoveryClient类:

      • 用于帮助与Eureka Server互相协作
      • Eureka Server负责任务:
        • 向Eureka server注册服务实例
        • 向Eureka Server服务租约
        • 当服务关闭期间,向Eureka Server取消租约
        • 查询Eureka Server中的服务实例列表
          • EndpointUtils类中getServiceUrlsMapFromConfig函数
          • Region Zone
            • 通过getRegion函数从配置中读取一个region返回,所以一个微服务应用只可以属于一个region,不特别配置为default,eureka.client.region属性定义
            • getAvailabilityZones函数,没有特别为region配置zone的时候默认defaultZone,可以通过eureka.client.availablity-zones属性设置,zone可以设置多个,逗号分隔开
            • region和zone是一对多的关系
          • serviceUrls
            • 获取region和zone之后才开始加载Eureka server的具体地址,根据传入的参数按一定算法确定加载位于哪个zone配置的serviceUrls
            • defaultZone属性可以配置多个并且需要通过逗号分隔
            • 当微服务使用ribbon实现服务调用时,对于zone的设置可以在负载均衡时,实现区域亲和特性,ribbon默认策略会优先访问同客户端处于一个zone中的服务端实例,如果没有可用服务实例才会访问其他zone中的实例。所以通过zone属性定义,配合实际部署的物理结构,可以有效设计出对区域性故障容错集群。
        • 服务注册:
          • DiscoveryClient类initScheduledTasks中 if(clientConifg.shouldRegisterWithEureka()),分支内,创建了一个InstanceInfoReplicator类的实例,会执行一个定时任务
          • 定时任务 discoveryClient.register真正触发调用注册的地方。注册操作通过rest请求方式进行。发起注册请求时参数有InstanceInfo对象(是注册时客户端的服务的元数据)
        • 服务获取与服务续约:initScheduledTasks中的其他两个定时任务
          • 服务注册和服务续约在同一个if逻辑中,防止被剔除
            • 服务续约相关时间控制参数:
            • eureka.instance.lease-renewal-interval-in-seconds=30
            • eureka.instance.lease-expiration-duration-in-seconds=90
          • 服务续约:直接以rest请求方式进行续约
          • 服务获取是在独立的一个if判断中,判断依据是eureka.client.fetch-registry=true参数,默认为true。不止限于服务启动,是一个定时执行任务。
            • 会根据是否是第一次获取发起不同的rest请求和相应的处理。
        • 服务注册中心处理
          • 所有交互都是通过REST请求发起的,服务注册中心对各类rest请求的定义都位于eureka.resources包下
          • eg:服务注册请求
            • 对注册信息进行一堆校验之后,会调用InstanceRegistry对象中的register函数进行服务注册
            • register函数注册
              • 先调用publishEvent函数,将该新服务注册的事件传播出去
              • 调用AbstractInstanceRegistry父类中的InstanceInfo中的元数据信息存储在一个concurrentHashMap对象中
                • 注册中心存储了两层map
                  • 第一层,key存储服务名,InstanceInfo中的appName
                  • 第二层,key存储实例名,InstanceInfo中的instanceId属性
  • 在application.properties中用eureka.client.serviceUrl.defaultZone参数指定了服务注册中心的位置

配置详解

  • 服务端为服务注册中心
  • 客户端为各个提供接口的微服务应用

Eureka客户端的配置主要分为:

  • 服务注册相关的配置信息:包括服务注册中心的地址,服务获取的间隔时间,可用区域等
  • 服务实例相关的配置信息:包括服务实例的名称,ip地址,端口号,健康检查路径等

服务注册类配置

这些配置信息都以eureka.client为前缀。常用配置为:

  • 指定注册中心
    • 参数:eureka.client.serviceUrl
      • 配置值存储在hashmap中,设置有一组默认值,key:defaultzone value:ip:port/eureka(多个使用逗号分隔开)
      • 为了服务注册中心的安全考虑,会为服务注册中心加入安全校验,配置serviceUrl时,需要在value值url中加入相应的安全校验信息
  • 其他配置

服务实例类配置

配置信息以eureka.instance为前缀

  • 元数据

    • eureka客户端在向服务注册中心发送注册请求时,用来描述自身服务信息的对象,其中包含一些标准化的元数据,比如服务名称,实例名称,实例端口等用于服务治理的重要信息,以及负载均衡策略或是其他特殊用途的自定义元数据信息

    • 真正服务注册的时候,会包装成InstanceInfo对象发送给Eureka服务端。

    • Map<String,String> metadata 是自定义元数据信息,其他成员变量则是标准化的元数据信息

    • 可以通过eureka.instance.=格式对标准化元数据直接进行配置

    • eureka.instance.metadataMap.zone=shanghai
      
  • 实例名配置

    • InstanceInfo中的instanceId参数是区分同一服务中不同实例的唯一标识。
    • 实例名采用主机名作为默认值,使得在同一主机上无法启动多个相同的服务实例。针对同一主机多个服务实例的情况,对实例的默认命名做了更为合理的扩展。
    • eg:本地负载均衡调试时,统一服务多个实例,命名:利用应用名加随机数的方式来区分不同的实例,从而实现在统一主机上,不指定端口就能轻松启动多个实例的效果
  • 端点配置

    • 状态页和健康检查的url在eureka中默认使用了actuator模块提供的/info端点和/health端点
    • 为应用设置了context-path或为安全考虑修改了路径,需要做些特殊配置
      • 相对路径配置
        • eureka.instance.statusPageUrlPath
        • eureka.instance.healthCheckUrlPath
      • 绝对路径配置(eg以https方式暴露服务和监控端点时)
        • eureka.instance.statusPageUrl
        • eureka.instance.healthCheckUrl
        • eureka.instance.homePageUrl
  • 健康检测

    • 默认情况下,是依靠客户端心跳的方式来保持服务实例的存活,但有些情况不能判断
    • 通过配置,把eureka客户端的健康检测交给spring-boot-actuator模块/health端点,实现更加全面的健康状态维护
      • 步骤
      • 在pom.xml中引入spring-boot-starter-actuator模块的依赖
      • 在application.properties中增加增加配置eureka.client.healthcheck.enable=true
      • 如果客户端的/health端点路径做了一些特殊处理。
  • 其他配置

    • 默认前缀eureka.instance

跨平台支持

参考:《spring cloud 微服务实战》

相关文章:

spring Cloud笔记--服务治理Eureka

服务治理&#xff1a;Eureka 服务治理 主要用来实现各个微服务实例的自动化注册与发现 服务注册&#xff1a; 服务治理框架中&#xff0c;通常会构建一个注册中心&#xff0c;每个服务单元向注册中心登记自己提供的服务&#xff0c;将主机与端口号&#xff0c;版本号&#x…...

pdf压缩文件怎么压缩最小?pdf压缩方法汇总

PDF是一种常见的文件格式&#xff0c;通常用于电子文档和印刷品&#xff0c;由于PDF文件通常包含大量的元数据、字体、图像和其他元素&#xff0c;因此它们的大小可能会非常大。 为了解决这个问题&#xff0c;我们可以使用一些PDF压缩工具来帮助我们&#xff0c;以便我们能够更…...

Golang学习记录:基础篇练习(一)

Golang学习记录&#xff1a;基础篇练习&#xff08;一&#xff09; 1、九九乘法表2、水仙花数3、斐波那契数列4、编写一个函数&#xff0c;求100以内的质数5、统计字符串里面的字母、数字、空格以及其他字符的个数6、二维数组对角线的和7、冒泡排序算法8、选择排序算法9、二分查…...

sql注入(7), python 实现盲注爆破数据库名, 表名, 列名

python 实现盲注 该python脚本根据之前介绍的盲注原理实现, 对于发送的注入请求没有做等待间隔, 可能给目标服务器造成一定 压力, 所以仅限于本地测试使用. import requests, time# 时间型盲注 def time_blind(base_url, cookie):for length in range(1, 20): # 测试数据库名…...

2021年12月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 执行以下程序 a[33,55,22,77] a.sort() for i in a:print(i)运行…...

卡尔曼家族从零解剖-(01)预备知识点

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…...

技术分享| 二进制部署MySQL

一、介绍 ​MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database Management System&#x…...

3.1 模板测试与深度测试(Stencil Test Z Test)

一、模板测试&#xff08;Stencil Test&#xff09; 模板测试可以实现的一些效果图 1.是什么 ①从渲染管线出发&#xff1a;模板测试是在逐片源操作阶段&#xff0c;透明测试之后&#xff0c;深度测试之前的位置。 ②从书面概念上理解 说到模板测试&#xff0c;就要先说道模…...

一些常见的必须会的谭浩强基本代码大全也是常考的应试是没问题的

//1. 1£¡+2£¡+3£¡+...20! /* #include <stdio.h> int main() {int i;long sum=0,k=1;for(i=1;i<=20;i++){k*=i;sum+=k;}printf("%d",sum); } *///方法2 /* #include <stdio.h> int main() {int i,j;long sum=0,k;for(i…...

C语言天花板——指针(进阶1)

接上次的指针初阶&#xff08;http://t.csdnimg.cn/oox5s&#xff09;&#xff0c;这次我们继续的探寻指针的奥秘&#xff0c;发车咯&#xff01;&#xff01;&#xff01;&#x1f697;&#x1f697;&#x1f697; 一、字符指针 可以看到我们将指针p给打印出来&#xff0c;就是…...

二、深度测试(Z Test)

1.是什么 ①从渲染管线出发 ②书面上理解 所谓深度测试&#xff0c;就是针对当前对象在屏幕上&#xff08;更准确的说是frame buffer&#xff09;对应的像素点&#xff0c;讲对象自身的深度值与当前该像素点缓存的深度值进行比较&#xff0c;如果通过了&#xff0c;本对象再改…...

Vue_Bug VUE-ADMIN-TEMPLATE-MASTER electron build后无法登录

Bug描述&#xff1a; VUE-ADMIN-TEMPLATE-MASTER 项目在经过 electron 的 build 命令后&#xff0c;无法登录 问题原因&#xff1a; 大部分vue 前段项目 会使用 js-cookie 这个库 来操作浏览器的cookie 然而这个库 在electron下 会无法使用 &#xff08;最坑的是还没报错&…...

睡衣内衣服装商城小程序的作用是什么

服装行业一直都是市场很重要的组成部分&#xff0c;每个人都需要&#xff0c;且根据品牌、样式作用等可以细分很多类目&#xff0c;其中睡衣内衣也有不小的市场规模&#xff0c;从业商家多、市场需求度高。 但同时睡衣内衣经营痛点也比较明显。 当今消费者习惯于线上消费&…...

idea怎么设置作者信息(详细)

目录 一&#xff1a;在Java类的开头自动注释作者名字和日期等信息 二&#xff1a;给Java的方法注释作者名字和日期等信息 1. 不可修改的模板&#xff1a;Postfix Completion 2. 可修改的模板&#xff1a;Live Templates tips&#xff1a;首先给大家推荐两款好用的免费软件&…...

产品经理如何有效跟进开发进度?

作为产品经理&#xff0c;很难跟进开发过程。随着软件开发的复杂性和不断变化的产品环境&#xff0c;产品经理必须保持在开发过程的顶端&#xff0c;并确保目标得到满足。产品经理如何跟进开发进度&#xff1f; 第一步是对开发过程本身有一个扎实的理解。产品经理必须熟悉开发过…...

【已解决】Qt无法追踪到mouse移动事件

本博文源于笔者正在亲身经历的Qt无法追踪到鼠标移动事件。事情是这样的&#xff0c;笔者有一个应用程序&#xff0c;当应用程序移动进窗口里的时候&#xff0c;每移动一下&#xff0c;检测鼠标位置&#xff0c;进而调整鼠标的形状&#xff0c;结果发现它这死活不听话。后来解决…...

Dubbo从0到1——万字完整学习笔记

目录 RPC理论概述 RPC的基本思想 RPC的实现组成部分 RPC的实现流程 RPC的核心思想 RPC调用分类 初识Dubbo Dubbo特性 Dubbo设计架构 zookeeper环境搭建 搭建注册中心环境 搭建监控中心环境 Dubbo入门案例(Dubbo Spring) 实现步骤 搭建中介者组件共享资源 打包为jar&#xf…...

Rust初接触

一、什么是Rust Rust 是由 Mozilla 开发的多范式编程语言&#xff0c;专注于性能和安全性。 Rust 以其先进的安全并发能力而闻名&#xff0c; 它的语法类似于 C&#xff0c;但它提供了更快的速度和内存安全性&#xff0c;但不使用垃圾收集器。 Rust 最初是为 Mozilla Firefox …...

shell脚本学习笔记03(小滴课堂)

在shell脚本中&#xff0c;表示变量除了可以使用$a(a是一个变量)&#xff0c;还可以使用${a} 那这两种表示方式有什么区别么&#xff1f; 花括号可以和其它字符或者字母区分开来。 >追加内容 我们发现使用>会把原来的内容覆盖。 我们使用>>就不会覆盖了&#xff…...

软件工程和计算机科学与技术学习方向区别

软件工程&#xff08;Software Engineering&#xff09;和计算机科学与技术&#xff08;Computer Science and Technology&#xff09;是两个相关但不同的领域&#xff0c;它们涉及到计算机和软件的不同方面。以下是它们之间的主要区别&#xff1a; 计算机科学与技术&#xff…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中&#xff0c;如何展示好看的实验结果图像非常重要&#xff01;&#xff01;&#xff01; 1、灰度原始图像 灰度图像每个像素点只有一个数值&#xff0c;代表该点的​​亮度&#xff08;或…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)

旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据&#xff01;该数据集源自2025年4月发表于《地理学报》的论文成果…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...

CMS内容管理系统的设计与实现:多站点模式的实现

在一套内容管理系统中&#xff0c;其实有很多站点&#xff0c;比如企业门户网站&#xff0c;产品手册&#xff0c;知识帮助手册等&#xff0c;因此会需要多个站点&#xff0c;甚至PC、mobile、ipad各有一个站点。 每个站点关联的有站点所在目录及所属的域名。 一、站点表设计…...

Python异步编程:深入理解协程的原理与实践指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…...