《springcloud 一》搭建注册中心,服务提供者,服务消费者

注册中心环境搭建

Maven依赖信息  

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <!-- 管理依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!--SpringCloud eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

application.yml

###服务端口号
server:
  port: 8100
###eureka 基本信息配置
eureka:
  instance:
    ###注册到eurekaip地址
    hostname: 127.0.0.1
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
###因为自己是为注册中心,不需要自己注册自己
    register-with-eureka: false
###因为自己是为注册中心,不需要检索服务
    fetch-registry: false

启动Eureka服务

@EnableEurekaServer
@SpringBootApplication
public class AppEureka {

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

}

 

注册服务提供者

Maven依赖信息

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <!-- 管理依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- SpringBoot整合eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

application.yml

###服务启动端口号
server:
  port: 8000
###服务名称(服务注册到eureka名称)  
spring:
    application:
        name: app-itmayiedu-member
###服务注册到eureka地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8100/eureka

           
###因为该应用为注册中心,不会注册自己
    register-with-eureka: true
###是否需要从eureka上获取注册信息
    fetch-registry: true

服务接口

@RestController
public class MemberController {

    @RequestMapping("/getMember")
    public String getMember() {
        return "this is getMember";
    }
}

启动会员服务

@SpringBootApplication
@EnableEurekaClient
public class AppMember {

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

}

服务消费者

Maven依赖信息

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <!-- 管理依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M7</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- SpringBoot整合eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

    </dependencies>
    <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

Application.yml配置

###服务启动端口号
server:
  port: 8001
###服务名称(服务注册到eureka名称)  
spring:
    application:
        name: app-itmayiedu-order
###服务注册到eureka地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8100/eureka

           
###因为该应用为注册中心,不会注册自己
    register-with-eureka: true
###是否需要从eureka上获取注册信息
    fetch-registry: true

使用rest方式调用服务

@RestController
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/getorder")
    public String getOrder() {
        // order 使用rpc 远程调用技术 调用 会员服务
        String memberUrl = "http://app-itmayiedu-member/getMember";
        String result = restTemplate.getForObject(memberUrl, String.class);
        System.out.println("会员服务调用订单服务,result:" + result);
        return result;
    }

}

 

启动消费者服务

@SpringBootApplication
@EnableEurekaClient
public class AppOrder {

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

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

@LoadBalanced就能让这个RestTemplate在请求时拥有客户端负载均衡的能力

高可用注册中心

 

在微服务中,注册中心非常核心,可以实现服务治理,如果一旦注册出现故障的时候,可能会导致整个微服务无法访问,在这时候就需要对注册中心实现高可用集群模式。

 

Eureka高可用原理

默认情况下Eureka是让服务注册中心,不注册自己

###注册自己
    register-with-eureka: true
###需要去注册中心上检索服务
    fetch-registry: true

Eureka高可用实际上将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组相互注册的服务注册中心,从而实现服务清单的互相同步,达到高可用效果。

 

客户端集成Eureka集群

server:
  port: 8000
spring:
  application:
    name: app-itmayiedu-member
#eureka:
#  client:
#    service-url:
#      defaultZone: http://localhost:8100/eureka
###集群地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8100/eureka,http://localhost:8200/eureka    
    register-with-eureka: true
    fetch-registry: true

Eureka详解

 

服务消费者模式

 

获取服务

 消费者启动的时候,使用服务别名,会发送一个rest请求到服务注册中心获取对应的服务信息,让后会缓存到本地jvm客户端中,同时客户端每隔30秒从服务器上更新一次。

可以通过 fetch-inte vall-seconds=30参数进行修以通过eureka.client .registry该参数默认值为30 单位为秒。

 

 

 

服务下线

    在系统运行过程中必然会面临关闭或重启服务的某个实例的情况,在服务关闭期有我们自然不希望客户端会继续调用关闭了的实例。所以在客户端程序中,当服务实例过正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server, 告诉服务日中心:“我要下线了”。服务端在接收到请求之后,将该服务状态置为下线(DOWN),井该下线事件传播出去。

 

服务注册模式

 失效剔除

 有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障气因使得服务不能正常工作,而服务注册中心并未收到“服务下线”的请求。为了从服务表中将这些无法提供服务的实例剔除,Eureka Server 在启动的时候会创建一个定时任多默认每隔一一段时间(默认为60)将当前清单中超时(默认为90)没有续约的服务除出去

 自我保护

 

 

默认情况下,EurekaClient会定时向EurekaServer端发送心跳,如果EurekaServer在一定时间内没有收到EurekaClient发送的心跳,便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出该服务。

 

产生的原因:

 

在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews thresholdRenews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:

 

EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.

 

从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。

该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。

但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:

 

 

 

但在生产环境,不会频繁重启,所以,一定要把自我保护机制打开,否则网络一旦终端,就无法恢复。

当然关于自我保护还有很多个性化配置,这里不详细说明。

 

注意考虑网络不可达情况下:调用接口幂等、重试、补偿等。

 

 

关闭服务保护

Eureka服务器端配置
###服务端口号
server:
  port: 8100
##定义服务名称
spring:
  application:
    name: app-itmayiedu-eureka
eureka:
  instance:
    ###注册中心ip地址
    hostname: 127.0.0.1
  client:
    serviceUrl:
    ##注册地址
      defaultZone: http://${eureka.instance.hostname}:8100/eureka/
    ####因为自己是注册中心,是否需要将自己注册给自己的注册中心(集群的时候是需要是为true)
    register-with-eureka: false
    ###因为自己是注册中心, 不需要去检索服务信息
    fetch-registry: false
  server:
    # 测试时关闭自我保护机制,保证不可用服务及时踢出
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000
Eureka客户端配置
###订单服务的端口号
server:
  port: 8001
###服务别名----服务注册到注册中心名称 
spring:
  application:
    name: app-itmayiedu-order
eureka:
  client:
    service-url:
    ##### 当前会员服务注册到eureka服务地址
#      defaultZone: http://localhost:8100/eureka,http://localhost:9100/eureka
       defaultZone: http://localhost:8100/eureka
    ### 需要将我的服务注册到eureka上
    register-with-eureka: true
    ####需要检索服务
    fetch-registry: true
    registry-fetch-interval-seconds: 30
# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
  instance:
###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)  
    lease-renewal-interval-in-seconds: 1
####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)
    lease-expiration-duration-in-seconds: 2    

声明式服务调用SpringCloud Feign             主流

feign介绍

Feign客户端是一个web声明式http远程调用工具,提供了接口和注解方式进行调用。

 

 

环境搭建

Maven依赖信息

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

feign客户端接口

// name 指定服务名称
@FeignClient(name = "app-itmayiedu-member")
public interface MemberApifeign {

    @RequestMapping("/getMember")
    public String getMember();

}

controller

    @Autowired
    private MemberApifeign memberApifeign;

    @RequestMapping("/feignMember")
    public String feignMember() {
        return memberApifeign.getMember();
    }

项目启动加上@EnableFeignClients

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

}

Ribbon配置

 

SpringCloud Feign客户端Http调用工具,默认已经整合了Ribbon负载均衡客户端。

 

配置Feign客户端超时时间

###设置feign客户端超时时间
ribbon:
###指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间。
 ReadTimeout: 5000
###指的是建立连接后从服务器读取到可用资源所用的时间。 
 ConnectTimeout: 5000

@RestController

publicclass OrderController {

      @Autowired

      private RestTemplate restTemplate;

 

      @RequestMapping("/getorder")

      public String getOrder() {

           // order 使用rpc远程调用技术 调用 会员服务

           String memberUrl = "http://app-itmayiedu-member/getMember";

           String result = restTemplate.getForObject(memberUrl, String.class);

           System.out.println("会员服务调用订单服务,result:" + result);

           returnresult;

      }

 

}

 

猜你喜欢

转载自www.cnblogs.com/a1304908180/p/10676396.html