Spring Cloud 微服务注册与发现

Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)。分布式系统的协调导致了样板模式, 使用Spring Cloud开发人员可以快速地支持实现这些模式的服务和应用程序。他们将在任何分布式环境中运行良好,包括开发人员自己的笔记本电脑,裸机数据中心,以及Cloud Foundry等托管平台。

 

Spring Cloud专注于提供良好的开箱即用经验的典型用例和可扩展性机制覆盖。

•       分布式/版本化配置

•       服务注册和发现

•       路由

•       service - to - service调用

•       负载均衡

•       断路器

•       分布式消息传递

 

 

微服务注册与发现

 

服务发现是基于微服务架构的关键原则之一。

服务提供者,服务消费者,服务发现组件这三者之间的关系大概如下:


       各个微服务在启动时,将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些信息。

       服务消费者可从服务发现组件查询服务提供者的网络地址,并使用该地址调用服务提供者的接口。

       各个微服务与服务发现组件使用一定机制(心跳)通信。服务发现组件如果长时间无法与某微服务实例通信,就会注销该实例。

 

Spring Cloud提供了多种服务发现组件的支持,例如Eureka,Consul,Zookeeper等。

 

Eureka是Netflix开源的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。Spring将它集成在子项目Spring Cloud Netflix中。

先来看看Eureka的官方架构图


 

Application Service:服务提供者

Application Client: 服务消费者

 

Eureka Server提供服务发现的能力,各个微服务启动时,会向Eurekaserver 注册自己的信息(比如IP,端口,微服务名等),Eureka Server会存储这些信息。

Eureka Client是一个Java客户端,用于简化与EurekaServer的交互。

微服务启动后,会周期性(默认30秒)地向Eureka Server发送心跳。

如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)

 

默认情况下,Eureka Server同时也是Eureka Client。多个Eureka Server实例,互相之间通过复制的方式,来实现服务注册表中数据的同步。

Eureka Client会缓存服务注册表中的信息。微服务无须每次请求都查询Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server所有节点都宕机,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用。

 

编写Eureka Server

 

先创建一个Spring Boot项目:

项目pom.xml (这块之前写错了,重新更新一下)

 

<?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">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.learn</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <modules>
      <module>eureka-server</module>
      <module>demo-provider-user</module>
   </modules>
   <packaging>pom</packaging>

   <name>demo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</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>
      </dependencies>
   </dependencyManagement>

</project>

 

 

创建一个eureka-server组件, pom.xml

 

<?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">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>com.learn</groupId>
      <artifactId>demo</artifactId>
      <version>0.0.1-SNAPSHOT</version>
   </parent>

   <artifactId>eureka-sever</artifactId>
   <packaging>jar</packaging>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

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

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

</project>

 

application.yml

server:
  #Eureka Server的端口
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    #是否将自己注册到Eureka Server
    register-with-eureka: false
    #是否从Eureka Server获取注册信息
    fetch-registry: false
    #设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

 

logback.xml:

 

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

<configuration scan="true" scanPeriod="10 seconds">

    <!--定义日志文件的存储地址和前缀名-->
    <property name="LOG_HOME" value="F://learn//logs" />
    <property name="LOG_PREFIX" value="demo-eureka-server" />

    <!-- 一般信息按照每天生成日志文件 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_HOME}/${LOG_PREFIX}-info.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 每天一归档 -->
            <fileNamePattern>${LOG_HOME}/${LOG_PREFIX}-info-%d{yyyyMMdd}.log.%i</fileNamePattern>
            <!-- 单个日志文件最多500MB, 30天的日志周期,最大不能超过20GB -->
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n</Pattern>
        </encoder>
    </appender>

    <!--错误信息按照每天生成日志文件-->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <File>${LOG_HOME}/${LOG_PREFIX}-error.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 每天一归档 -->
            <fileNamePattern>${LOG_HOME}/${LOG_PREFIX}-error-%d{yyyyMMdd}.log.%i</fileNamePattern>
            <!-- 单个日志文件最多500MB, 30天的日志周期,最大不能超过20GB -->
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n</Pattern>
        </encoder>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 日志输出级别 -->
    <root level="INFO">
        <!-- <appender-ref ref="STDOUT" /> -->
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>

</configuration>

 

 

EurekaServerApplication.java

 

package com.learn.eurekasever;

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

//声明是一个Eureka Server
@EnableEurekaServer
@SpringBootApplication
public class EurekaSeverApplication {

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

 

 启动一下,并访问http://localhost:8761


 


新建一个微服务,并将其注册到Eureka Server上

pom.xml:

<?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">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>com.learn</groupId>
      <artifactId>demo</artifactId>
      <version>0.0.1-SNAPSHOT</version>
   </parent>

   <artifactId>demo-provider-user</artifactId>
   <packaging>jar</packaging>

   <name>demo-provider-user</name>
   <description>Demo project for Spring Boot</description>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

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

</project>

 

 

application.yml

 

spring:
  application:
    #注册到Eureka Server上的应用名称
    name: demo-provider-user
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    #将自己的IP注册到Eureka Server
    prefer-ip-address: true

DemoProviderUserApplication.java

 

package com.learn.demoprovideruser;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

//声明这是一个Eureka Client
@EnableEurekaClient
@SpringBootApplication
public class DemoProviderUserApplication {

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

 

先运行Eureka-server节点,然后运行DemoProviderUser节点,重新进入http://localhost:8761,看看新启动的微服务是否已经注册到eureka上了

 

当然,在实际的生产环境上,Eureka Client会定时连接Eureka Server,获取服务注册表中的信息并缓存在本地。即便Eureka Server发生宕机,也不能影响到服务之间的调用。如果是单节点Eureka Server发生宕机的话,某些微服务一旦出现了不可用的情况,Eureka Client中的缓存不被及时更新,就可能会影响到微服务的调用,甚至影响到整个应用系统的高可用。因此在实际生产环境中,通常会部署一个高可用的Eureka Server集群。


在这边,我们把eureka server组件进行一下更新

pom.xml修改成

<artifactId>eureka-sever-ha</artifactId>

 

application.yml修改成

spring:
  application:
    name: eureka-server-ha

---
spring:
  profiles: peer1
server:
  #Eureka Server的端口
  port: 8761
eureka:
  instance:
    hostname: peer1
  client:
    service-url:
      defaultZone: http://peer2:8762/eureka/
---
spring:
  profiles: peer2
server:
  #Eureka Server的端口
  port: 8762
eureka:
  instance:
    hostname: peer2
  client:
    service-url:
      defaultZone: http://peer1:8761/eureka/

 

将Eureka-server组件打包成jar包,然后用命令行到jar 包所在位置

用java –jar xxxx.jar –spring-profiles-active=peer1, java –jar xxxx.jar–spring-profiles-active=peer2分别启动两个节点,我们的eureka-server集群环境就搭建好了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值