springcloud之eureka注册中心

Spring提供了一系列工具,可以帮助开发人员迅速搭建分布式系统中的公共组件。协调分布式环境中各个系统,为各类服务提供模板性配置。使用Spring Cloud, 开发人员可以搭建实现了这些样板的应用,并且在任何分布式环境下都能工作得非常好,小到笔记本电脑, 大到数据中心和云平台。

eureka注册中心

简介

 

Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server
它提供了注册服务的功能,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中会将存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client
它是一个Java客户端,用于简化与Eureka Server的交互,客户端同事也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接受到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即时所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
Eureka现已闭源,停止更新,处于维护阶段。不过目前已经很稳定,依旧可以使用。也可以使用Consul、zookeeper等替换
高可用环境搭建
Eureka Server 高可用环境需要部署两个Eureka server,它们互相向对方注册。如果在本机启动两个Eureka需要注意两个Eureka Server的端口要设置不一样,这里我们部署一个Eureka Server工程,将端口可配置,制作两个Eureka Server启动脚本,启动不同的端口,如下图:
684883eeffb698165d9c733395f650bed94.jpg
1、在实际使用时Eureka Server至少部署两台服务器,实现高可用。
2、两台Eureka Server互相注册。
3、微服务需要连接两台Eureka Server注册,当其中一台Eureka死掉也不会影响服务的注册与发现。
4、微服务会定时向Eureka server发送心跳,报告自己的状态。
5、微服务从注册中心获取服务地址以RESTful方式发起远程调用。
 
最外层父工配置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.itheima</groupId>
    <artifactId>springcloud-parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springcloud-server</module>
        <module>springcloud-provider</module>
        <module>springcloud-consumer</module>
        <module>springcloud-provider1</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <spring.boot.version>2.1.2</spring.boot.version>
        <spring.cloud.version>Greenwich.RELEASE</spring.cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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注册中心:
 
首先编写eureka注册中心,也就是服务端。
该注册中心继承于上面方父module:springcloud-parent
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">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jaxb.version>2.3.1</jaxb.version>
    </properties>

    <artifactId>springcloud-server</artifactId>

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

</project>
 

配置文件:application.yml

server:
  port: ${PORT:8080}
  # springCloud应用都要指定application.name
spring:
  application:
    name: spring-eureka-server
  # 默认情况下eureka server也是一个eureka client,必须指定一个server
eureka:
  instance:
    hostname: ${EUREKA_DOMAIN:eureka01}
  server:
    enable-self-preservation: false #是否开启自我保护模式
    eviction-interval-timer-in-ms: 60000 #服务注册表清理间隔(单位毫秒,默认是60*1000)
  client:
    #register-with-eureka = false 和fetchRegistry=false 表明自己是一个eureka server
    registerWithEureka: true #服务注册,是否将自己注册到Eureka服务中
    fetchRegistry: true #服务发现,是否从Eureka中获取注册信息
    serviceUrl: #Eureka客户端与Eureka服务端的交互地址,高可用状态配置对方的地址,单机状态配置自己(如果不配置则默认本机8761端口)
        defaultZone: ${EUREKA_SERVER:http://eureka02:8081/eureka/}
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  //单个eureka注册中心,配置自己

 

 
启动类 Application.class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer // 启用EurekaServer
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

 

 
这里在本机启动两个Eureka需要注意两个Eureka Server的端口要设置不一样,这里我们部署一个Eureka Server工程,将端口可配置,制作两个Eureka Server启动脚本,启动不同的端口
dea246edaf61ea8115ee8c3b336ff8341b7.jpg
 
-DPORT=8080 -DEUREKA_SERVER= http://eureka02:8081/eureka/ -DEUREKA_DOMAIN=eureka01
-DPORT=8081 -DEUREKA_SERVER= http://eureka02:8080/eureka/ -DEUREKA_DOMAIN=eureka02
 
启动服务后,浏览器访问http://localhost:8080或者http://localhost:8081就是eureka的控制台了,这里可以看到注册的所有应用:
 
 
服务提供者  provider:
这里需要引入依赖eureka-client 【不管是服务提供者还是消费者,在eureka眼里都是客户端】
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">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-provider</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>


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

        <!-- 引入eureka client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

</project>

 

 
搭建provider集群时通过 spring.application.name===> spring-eureka-provider相互调用
配置文件中需要指定应用名称和配置中心地址:
application.yml
server:
  port: 8082

  # 服务于服务之间相互调用一般是根据这个name,搭建provider集群时通过此调用
spring:
  application:
    name: spring-eureka-provider

eureka:
  client:
    registerWithEureka: true #服务注册开关
    fetchRegistry: true #服务发现开关
    serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址,Eureka服务端为集群时,多个中间用逗号分隔
      defaultZone: ${EUREKA_SERVER:http://localhost:8080/eureka/,http://localhost:8081/eureka/}
  instance:
    prefer-ip-address:  true  #将自己的ip地址注册到Eureka服务中
    ip-address: ${IP_ADDRESS:127.0.0.1}
    instance-id: ${spring.application.name}:${server.port} #指定实例id

 

 
编写启动类,顺便提供一个restAPI服务
启动类:ProviderApplication.class
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@SpringBootApplication
@EnableEurekaClient
@RestController
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }


    @Value("${spring.application.name}")
    String providerName;

    @Value("${server.port}")
    String port;

    @GetMapping("/")
    public String demo(String name) {
        return String.format("hello %s ,this is %s and port is %s", name, providerName, port);
    }

}

 

允许平行运行,修改server.port运行两个provider
在eureka控制台查看信息,发现注册了两个服务
打开浏览器访问 http://localhost:8082/?name=zhangsan 正确返回
 
服务消费者  consumer:
 
ribbon客户端负载均衡:
springcloud提倡微服务采用 rest http 的方式。消费者在注册中心中发现服务后,需要通过 负载均衡 进行调度,springcloud全家桶提供了两种服务调用方式,一种是 ribbon+restTemplate ,另一种是 feign 。其中 feign 底层使用了 ribbon 。本文介绍 ribbon
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">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-consumer</artifactId>

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

        <!--引入eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--引入 netflix-ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.7.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>


</project>

 

 
application.yml
server:
  port: 8085

spring:
  application:
    name: springcloud-consumer

eureka:
  client:
    service-url:
      defaultZone: ${EUREKA_SERVER:http://localhost:8080/eureka/,http://localhost:8081/eureka/}
ribbon:
  MaxAutoRetries: 2 #最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试
  MaxAutoRetriesNextServer: 3 #切换实例的重试次数
  OkToRetryOnAllOperations: false  #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
  ConnectTimeout: 5000  #请求连接的超时时间
  ReadTimeout: 6000 #请求处理的超时时间

 

 
启动类 ConsumerApplication.class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
//@EnableDiscoveryClient // 启用服务发现组件 如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么使用@EnableDiscoveryClient。
public class ConsumerApplication {

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

    /**
     * springcloud中提倡rest风格的微服务
     * 向spring容器中注入RestTemplate
     *
     * 使用LoadBalanced表明这个restRemplate开启负载均衡的功能。
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

 

启动类中通过注解启用了Eureka和服务发现组件,并且向spring容器中注入了开启了负载均衡功能的RestTemplate。
 
 
controller 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


@RestController
public class HelloController {

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/")
    public String sayHi(String name) {
        return restTemplate.getForObject("http://SPRING-EUREKA-PROVIDER?name=" + name, String.class);
    }
}

 

这里直接写的是服务名: SPRING-EUREKA-PROVIDER 。在ribbon中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的url替换掉服务名
启动服务,浏览器多次访问http://localhost:8085/?name=zhangsan,会发现结果会轮询出现 port 8081和port8082。这是因为我们服务提供者启动了两个,端口分别是8082和8083,通过ribbon进行了客户端负载均衡。
这时我们再看一下注册中心,里面展示了两个服务提供者,一个消费者
 

feign客户端负载均衡:

 
将robbin依赖修改为feign
<?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>springcloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>


    <artifactId>springcloud-consumer_feign</artifactId>


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


        <!--引入eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--引入 feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.7.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

</project>

 

 
启动类开启feign服务
@SpringBootApplication
@EnableEurekaClient
//@EnableDiscoveryClient // 启用服务发现组件 如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么使用@EnableDiscoveryClient。
@EnableFeignClients  //开启Feign的功能
public class ConsumerFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignApplication.class, args);
    }
}

 

feign采用这种编写方式,声明一个interface接口,开启Feign负载均衡
/**
* 通过FeignClient配置负载均衡,指定了服务提供者的名字
*/
@FeignClient(value = "spring-eureka-provider")
public interface FeignService {
    //这里指定请求调用的rest URL
    @RequestMapping(value = "/", method = RequestMethod.GET)
    String sayHi(@RequestParam(value = "name") String name);


    @RequestMapping(value = "/getname/{id}", method = RequestMethod.GET)
    public String get(@PathVariable("id") long id);


}

 

 
编写controller调用服务
@RestController
public class HelloController {

//    @Autowired
//    RestTemplate restTemplate;

    @Autowired
    FeignService feignService;


    @GetMapping("/")
    public String sayHi(String name) {
//        return restTemplate.getForObject("http://SPRING-EUREKA-PROVIDER?name=" + name, String.class);
        return feignService.sayHi(name);
    }
}

 

 
启动服务,浏览器访问同样会有两个port结果
spring cloud的 Netflix 中提供了两个组件实现软负载均衡调用:ribbon 和 feign 。
 
Ribbon
是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。
它可以 在客户端 配置 RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
 
Feign
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。
 
采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。
 
然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写 客户端变得非常容易。
 
类似于 mybatis 的 @Mapper注解 。
 
注意:spring-cloud-starter-feign 里面已经包含了 spring-cloud-starter-ribbon(Feign 中也使用了 Ribbon)
 
 
自我保护机制:
 
官方对于自我保护机制的定义:
自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。
自我保护机制的工作机制是如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制,此时会出现以下几种情况:
  1. Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
  2. Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。
  3. 当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。
因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪。

关闭自我保护

服务端配置
eureka:
  server:
    # 测试时关闭自我保护机制,保证不可用服务及时踢出
    enable-self-preservation: false

 

客户端配置
# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
eureka:
  instance:
    lease-renewal-interval-in-seconds: 1   # 每间隔1s,向服务端发送一次心跳,证明自己依然”存活“
    lease-expiration-duration-in-seconds: 2 # 告诉服务端,如果我2s之内没有给你发心跳,就代表我“死”了,将我踢出掉

 

 
这个只适用于测试环境,在生产环境不要关闭
##@EnableDiscoveryClient与@EnableEurekaClient
这两个注解非常类似,都是用作启用服务发现的
如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么使用@EnableDiscoveryClient。
 
 
 
 
 
 

转载于:https://my.oschina.net/wuaiting/blog/3069136

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值