首页 > 编程语言 > 详细

springcloud-eureka

时间:2019-04-07 10:27:31      阅读:163      评论:0      收藏:0      [点我收藏+]

以下代码提交到git:http://47.93.254.162:8090/open/registry_center.git

浏览更多open项目:http://47.93.254.162:8090/open

一、简介

  SpringCloud:基于SpringBoot基础上开发的微服务框架,是一套完整的微服务解决框架,其内容包含服务治理、注册中心、配置管理、路由管理、代理转发、控制总线、全局锁、分布式会话等。中文网:https://springcloud.cc/spring-cloud-dalston.html#spring-cloud-feign-hystrix-fallback。

  1. 微服务的解决方案:

  ①. 服务治理:Dubb(阿里巴巴)、Dubbox(当当网)、Eureka、Consul(Apache)。

  ②. 分布式配置中心:disconf(百度)、Archaius(Netflix)、QConf(360)、SpringCloud、Apollo(携程)。

  ③. 定时任务框架:xxl-job、elastic-job、task(SpringCloud)。

  ④. 服务追踪:hyra(京东)、sleuth(SpringCloud)。

  2.框架结构

  SpringCloud Config:配置中心。

  SpringCloud Netflix:核心注解。

    ①. Eureka:服务治理、注册中心。

    ②. Hystrix: 服务保护框架。

    ③. Ribbon:客户端负载均衡。

    ④. Feign:基于ribbon和hystrix的声明式服务调用组件(类似于Dubbo,但dubbo走的是tcp协议,feign是http协议)。

    ⑤. Zuul:网关组件、提供智能路由,访问过滤。

       架构图

               技术分享图片

二、服务治理Eureka(单机版)

  1.  服务治理:用于解决在远程调用rpc中服务于服务之间的依赖关系,可实现服务调、负载均衡、容错、服务的注册与发现。

  2. springboot搭建

    ①.pom文件引入

 1 <!-- 管理依赖 -->
 2     <dependencyManagement>
 3         <dependencies>
 4             <dependency>
 5                 <groupId>org.springframework.cloud</groupId>
 6                 <artifactId>spring-cloud-dependencies</artifactId>
 7                 <version>Finchley.M7</version>
 8                 <type>pom</type>
 9                 <scope>import</scope>
10             </dependency>
11         </dependencies>
12     </dependencyManagement>
13     <dependencies>
14         <!--SpringCloud eureka-server -->
15         <dependency>
16             <groupId>org.springframework.cloud</groupId>
17             <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
18         </dependency>
19         <!--spring-cloud 整合 config-server -->
20         <dependency>
21             <groupId>org.springframework.cloud</groupId>
22             <artifactId>spring-cloud-config-server</artifactId>
23         </dependency>
24         <!-- SpringBoot 整合Eureka客户端 -->
25         <dependency>
26             <groupId>org.springframework.cloud</groupId>
27             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
28         </dependency>
29     </dependencies>
30     <!-- 解决依赖有问题 -->
31     <repositories>
32         <repository>
33             <id>spring-milestones</id>
34             <name>Spring Milestones</name>
35             <url>https://repo.spring.io/libs-milestone</url>
36             <snapshots>
37                 <enabled>false</enabled>
38             </snapshots>
39         </repository>
40     </repositories>

    ②.application.yml文件

server:
  port: 8100
spring:
  application:
    name: eureka
eureka:
  instance:
    hostname: 127.0.0.1
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    #集群版将以下改成true(是否将自己注册)
    register-with-eureka: false
    #是否检索服务信息
    fetch-registry: false
  server:
    #关闭自我保护机制,保证不可用的服务及时删除(单机版使用)
    enable-self-preservation: false
    #心跳监测时间
    eviction-interval-time-in-ms: 2000

    ③. 启动类(@EnableEurekaServer:开启EurekaServer即服务端)

@SpringBootApplication
@EnableEurekaServer
public class AppEureka {

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

    ④. 访问地址

技术分享图片

  这里模拟一个生产者(produce)和一个消费者(consumer)调用环境

  produce搭建

 1 <!-- 管理依赖 -->
 2     <dependencyManagement>
 3         <dependencies>
 4             <dependency>
 5                 <groupId>org.springframework.cloud</groupId>
 6                 <artifactId>spring-cloud-dependencies</artifactId>
 7                 <version>Finchley.M7</version>
 8                 <type>pom</type>
 9                 <scope>import</scope>
10             </dependency>
11         </dependencies>
12     </dependencyManagement>
13     <dependencies>
14         <!-- SpringBoot整合Web组件 -->
15         <dependency>
16             <groupId>org.springframework.boot</groupId>
17             <artifactId>spring-boot-starter-web</artifactId>
18         </dependency>
19         <!-- SpringBoot整合eureka客户端 -->
20         <dependency>
21             <groupId>org.springframework.cloud</groupId>
22             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
23         </dependency>
24     </dependencies>
25     <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
26     <repositories>
27         <repository>
28             <id>spring-milestones</id>
29             <name>Spring Milestones</name>
30             <url>https://repo.spring.io/libs-milestone</url>
31             <snapshots>
32                 <enabled>false</enabled>
33             </snapshots>
34         </repository>
35     </repositories>

  application.yml

#服务启动端口号
server:
  port: 8200
#服务名称(服务注册到eureka名称)  
spring:
    application:
        name: app-produce
#服务注册到eureka地址
eureka:
  client:
    service-url:
           defaultZone: http://localhost:8100/eureka/
#因为该应用为注册中心,不会注册自己(集群使用)
    register-with-eureka: false
#是否需要从eureka上获取注册信息(集群使用)
    fetch-registry: false

   resource(controller)层

 1 @RestController
 2 public class ProduceResource {
 3 
 4     @RequestMapping("/produce")
 5     public String produce() {
 6         
 7         return "生成者返回正确消息...";
 8         
 9     }
10     
11 }

   启动类(@EnableEurekaClient: 客户端开启)

1 @SpringBootApplication
2 @EnableEurekaClient
3 public class AppProduce {
4 
5     public static void main(String[] args) throws Exception {
6         SpringApplication.run(AppProduce.class, args);
7     }
8     
9 }

  consumer搭建

pom文件和application.yml配置文件和produce一直,只需该端口即可

     ConsumerResource(Controller)搭建

 1 @RestController
 2 public class ConsumerResource {
 3     
 4     @Autowired
 5     private RestTemplate restTemplate;
 6     
 7     @RequestMapping("/consumer/rest")
 8     public String consumerRest() {
 9         
10         String productUrl = "http://product/produce";
11         String productResult = restTemplate.getForObject(productUrl, String.class);
12         
13         return productResult;
14         
15     }
16     
17 }

  注意:这里使用restTemplate调用,getForXXX方法可返回指定对象。(这里采用手动调用,一般在项目中不这么使用,这里只记录知识点)。

  启动类

 1 @SpringBootApplication
 2 @EnableEurekaClient
 3 public class AppConsumer {
 4 
 5     public static void main(String[] args) throws Exception {
 6         SpringApplication.run(AppConsumer.class, args);
 7     }
 8     
 9     @Bean
10     @LoadBalanced
11     RestTemplate restTemplate() {
12         return new RestTemplate();
13     }
14     
15 }

  注意:restTemplate() 方法作用是在RestTemplate在调用Produce时有负载均衡作用。

测试

技术分享图片

 

技术分享图片

三、服务治理Eureka(集群版)

  1. 搭建

  在微服务调用过程中,注册中心比较重要,但是一旦单机版出现故障会导致整个微服务无法访问,此时就需要对注册中心实现集群模式。
在Eureka集群中实际上将自己作为服务向其他服务注册中心注册自己,以此就可以形成一组相互注册的服务注册中心,实现服务清单的相互同步。
register-with-eureka: true 和 fetch-registry: true
Eureka1搭建过程
 1 #eureka配置中心
 2 server:
 3   port: 8000
 4 spring:
 5   application:
 6     name: eureka
 7 eureka:
 8   instance:
 9     hostname: 127.0.0.1
10   client:
11     serviceUrl:
12       #拼接地址
13       defaultZone: http://127.0.0.1:8100/eureka/
14     #集群版将以下改成true(是否将自己注册)
15     register-with-eureka: true
16     #是否检索服务信息
17     fetch-registry: true
18   #server:
19     #关闭自我保护机制,保证不可用的服务及时删除(单机版使用)
20     #enable-self-preservation: false
21     #心跳监测时间
22     #eviction-interval-time-in-ms: 2000

  注意:这里启动的端口是8000,但注册的是8100

  Eureka2搭建过程
 1 #eureka配置中心
 2 server:
 3   port: 8100
 4 spring:
 5   application:
 6     name: eureka
 7 eureka:
 8   instance:
 9     hostname: 127.0.0.1
10   client:
11     serviceUrl:
12       #拼接地址
13       defaultZone: http://127.0.0.1:8000/eureka/
14     #集群版将以下改成true(是否将自己注册)
15     register-with-eureka: true
16     #是否检索服务信息
17     fetch-registry: true
18   #server:
19     #关闭自我保护机制,保证不可用的服务及时删除(单机版使用)
20     #enable-self-preservation: false
21     #心跳监测时间
22     #eviction-interval-time-in-ms: 2000

  这里注册的8000

  生产者的application.yml

 1 ###服务启动端口号
 2 server:
 3   port: 8300
 4 ###服务名称(服务注册到eureka名称)  
 5 spring:
 6     application:
 7         name: app-produce
 8 ###服务注册到eureka地址 单机版
 9 #eureka:
10 #  client:
11 #    service-url:
12 #           defaultZone: http://localhost:8100/eureka
13 
14 ###服务注册到eureka地址 集群版
15 eureka:
16   client:
17     service-url:
18            defaultZone: http://localhost:8000/eureka,http://localhost:8100/eureka    
19 ###因为该应用为注册中心,不会注册自己
20     register-with-eureka: true
21 ###是否需要从eureka上获取注册信息
22     fetch-registry: true

     消费者的application.yml

 1 #服务启动端口号
 2 server:
 3   port: 8200
 4 #服务名称(服务注册到eureka名称)  
 5 spring:
 6     application:
 7         name: app-consumer
 8 #服务注册到eureka地址
 9 #eureka:
10 #  client:
11 #    service-url:
12 #           defaultZone: http://localhost:8100/eureka/
13 ###服务注册到eureka地址 集群版
14 eureka:
15   client:
16     service-url:
17            defaultZone: http://localhost:8000/eureka,http://localhost:8100/eureka
18 #因为该应用为注册中心,不会注册自己(集群使用)
19     register-with-eureka: true
20 #是否需要从eureka上获取注册信息(集群使用)
21     fetch-registry: true

  其他代码不变。

  2. 消费者模式:在Eureka启动时,会发送一个rest请求到服务注册中心获取对应服务信息,然后缓存到本地jvm中客户端每隔30秒后从服务器上更新一次,可以通过fetch-inte-vall-seconds=30进行修改eureka.client.registry的默认值。

  3. Eureka的下线:在系统运行过程中,当服务器正常关闭时,会触发一个服务下线的rest请求给Eureka的server。当服务端接收到后会将该服务状态置为下线DOWN,并且将该下线的服务广播出去。

  4. Eureka的失效剔除:对于服务实例由于网络故障、内存溢出等原因不能正常下线,服务端未收到下线请求,会导致服务列表中的实例无法正常提供服务。在Eureka server启动时会创建一个定时任务每个90秒将当前清单中超时的服务剔除出去。

  5. Eureka的自我保护:默认情况下Eureka client端会定时想Eureka server发送心跳包,在默认90秒钟没有收到请求变会将该服务剔除。但是Eureka server在短时间内(60秒)丢失大量的实例心跳时,Eureka server会开启自我保护机制,不会剔除该服务。

  • 产生原因:在开发测试阶段会频繁重启服务实例,但是不会重启Eureka server,当在一分钟内收到的心跳数大量减少时,会触发该保护机制,在Eureka界面中renews threshold和renews(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 server的配置文件中关闭。但是在生成环境中不会频繁重启,切记一定要将自我保护机制打开,否则网络一旦中断,服务实例不会恢复
  • enable-self-preservation: false。剔除服务时效时间eviction-interval-timer-in-ms: 2000。
     1 #eureka配置中心
     2 server:
     3   port: 8000
     4 spring:
     5   application:
     6     name: eureka
     7 eureka:
     8   instance:
     9     hostname: 127.0.0.1
    10   client:
    11     serviceUrl:
    12       #拼接地址
    13       defaultZone: http://127.0.0.1:8100/eureka/
    14     #集群版将以下改成true(是否将自己注册)
    15     register-with-eureka: true
    16     #是否检索服务信息
    17     fetch-registry: true
    18   #server:
    19     #关闭自我保护机制,保证不可用的服务及时删除(单机版使用)
    20     enable-self-preservation: false
    21     #心跳监测时间
    22     eviction-interval-time-in-ms: 2000
    23     

    客户端配置:

     1 ###服务启动端口号
     2 server:
     3   port: 8300
     4 ###服务名称(服务注册到eureka名称)  
     5 spring:
     6     application:
     7         name: app-produce
     8 ###服务注册到eureka地址 单机版
     9 #eureka:
    10 #  client:
    11 #    service-url:
    12 #           defaultZone: http://localhost:8100/eureka
    13 
    14 #服务注册到eureka地址 集群版
    15 eureka:
    16   client:
    17     service-url:
    18            defaultZone: http://localhost:8000/eureka,http://localhost:8100/eureka    
    19 #因为该应用为注册中心,不会注册自己
    20     register-with-eureka: true
    21 #是否需要从eureka上获取注册信息
    22     fetch-registry: true
    23     # 心跳检测检测与续约时间
    24     registry-fetch-interval-seconds: 30
    25   instance:
    26 #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)  
    27     lease-renewal-interval-in-seconds: 1
    28 ##Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)
    29     lease-expiration-duration-in-seconds: 2 

    至此eureka结束。

 四、服务治理consul

  1. consul简介:当eureka闭源了,可使用consul、zookeeper来代替其注册功能,实现服务的治理与发现。
  • consul由hashiCorp公司用Go语言开发基于raft协议,支持健康检查、http、dns协议提供了对Linux、Mac、Windows支持。与springcloud整合:

    https://springcloud.cc/spring-cloud-consul.html、下载:https://www.consul.io/downloads.html

  • consul搭建:

    ①添加环境变量:G:\linux\consul

    ②在cmd中运行:consul agent -dev -ui -node=cy    其中:-dev 以开发模式启动,-node 节点名称为cy,-ui 界面启动 

    ③ui界面: http://localhost:8500 

 

技术分享图片

技术分享图片

五、服务治理zookeeper

  原理:在zookeeper中采用临时节点用服务名称作为键,以ip访问路径为值 来保存。

  • 生成者搭建

  pom文件(生产者和消费者一样)

 1 <!-- 管理依赖 -->
 2     <dependencyManagement>
 3         <dependencies>
 4             <dependency>
 5                 <groupId>org.springframework.cloud</groupId>
 6                 <artifactId>spring-cloud-dependencies</artifactId>
 7                 <version>Finchley.M7</version>
 8                 <type>pom</type>
 9                 <scope>import</scope>
10             </dependency>
11         </dependencies>
12     </dependencyManagement>
13     <dependencies>
14         <!-- SpringBoot整合Web组件 -->
15         <dependency>
16             <groupId>org.springframework.boot</groupId>
17             <artifactId>spring-boot-starter-web</artifactId>
18         </dependency>
19         <!-- SpringBoot整合eureka客户端 -->
20         <dependency>
21             <groupId>org.springframework.cloud</groupId>
22             <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
23         </dependency>
24 
25     </dependencies>
26     <!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
27     <repositories>
28         <repository>
29             <id>spring-milestones</id>
30             <name>Spring Milestones</name>
31             <url>https://repo.spring.io/libs-milestone</url>
32             <snapshots>
33                 <enabled>false</enabled>
34             </snapshots>
35         </repository>
36     </repositories>

  application.yml

1 #生产者
2 server:
3   port: 8100
4 spring:
5   application:
6     name: zk-produce
7   cloud:
8     zookeeper:
9       connect-string: 127.0.0.1:2181

  控制层

 1 @RestController
 2 public class ProduceResource {
 3 
 4     @RequestMapping("/zk/produce")
 5     public String consulPorduce() {
 6         
 7         return "consul produce success";
 8     }
 9     
10 }

  启动类

1 @SpringBootApplication
2 @EnableDiscoveryClient
3 public class AppZKProduce {
4 
5     public static void main(String[] args) throws Exception {
6         SpringApplication.run(AppZKProduce.class, args);
7     }
8 }
  • 消费者搭建

  yml

1 #生产者
2 server:
3   port: 8200
4 spring:
5   application:
6     name: zk-consumer
7   cloud:
8     zookeeper:
9       connect-string: 127.0.0.1:2181

  控制层

 1 @RestController
 2 public class ConsumerResource {
 3 
 4     @Autowired
 5     private RestTemplate restTemplate;
 6     
 7     @Autowired
 8     private DiscoveryClient discoveryClient;
 9     
10     @RequestMapping("/zk/consumer")
11     public String consulConsumer() {
12 
13         String produceUrl = "http://zk-produce/zk/produce";
14         
15         
16         String reusltProduce = restTemplate.getForObject(produceUrl, String.class);
17         
18         return reusltProduce;
19     }
20     
21     @RequestMapping("/discoveryClient")
22     public List<ServiceInstance> discoveryClient() {
23         List<ServiceInstance> instances = discoveryClient.getInstances("zk-consumer");
24         for (ServiceInstance serviceInstance : instances) {
25             System.out.println("url:" + serviceInstance.getUri());
26         }
27         return instances;
28 
29     }
30 }

  启动类

 1 @SpringBootApplication
 2 @EnableDiscoveryClient
 3 public class AppZKConsumer {
 4 
 5     public static void main(String[] args) throws Exception {
 6         SpringApplication.run(AppZKConsumer.class, args);
 7     }
 8     
 9     @Bean
10     @LoadBalanced
11     RestTemplate restTemplate() {
12         return new RestTemplate();
13     }
14 }
  • 测试

  本地调用

技术分享图片

  远程调用

技术分享图片

  zk注册内容

技术分享图片

 

 六、Zk和Eureka区别(集群)

  • Consistency(一致性), 数据一致更新,所有数据变动都是同步的
  • Availability(可用性), 好的响应性能
  • Partition tolerance(分区容忍性) 可靠性

       CAP:请参考本博客的分布式事务原理。

  1. zk保证CP

    当向注册中心查询服务实例时,允许返回几分钟前注册的信息,但不能接受服务down掉不可用。即当master节点由于网络故障与其他节点失去联系,剩余的节点会重新选举leader,在选举过程中30~120秒期间会zk不可用,导致整个服务处于短暂的瘫痪。

   2. Eureka保证AP

    在设计时优先保证可用性,其每个节点都是平等的,节点之间down掉不会影响正常的节点工作。Eureka客户端向Eureka注册时如果出现连接失败,则会自动切换至其他节点,只要有一台Eureka健在,就能保证服务的可用性,只是可能查询不到目前最新的(不保证强一致性)。Eureka还有一种自我保护机制,如果在15分钟内超过80%的节点都没有正常的心跳,Eureka server认为客户端与注册中心网络故障会出现以下2中情况。

     ①. Eureka不再从注册列表中移除长时间没有收到心跳而过期的服务。

     ②. Eureka仍能接收新的服务注册和请求,但不会同步到其他节点(目的是保证当前节点可用)。

     当网络恢复时,当前实例新的注册信息会被同步到其他节点。因此当部分节点丢失后不会像zk那样会导致整个注册服务 出现短暂瘫痪。

七、other

  1. 模拟ribbon的本地负载均衡
 1 @RestController
 2 public class ConsumerResource {
 3 
 4     @Autowired
 5     private RestTemplate restTemplate;
 6     
 7     @Autowired
 8     private DiscoveryClient discoveryClient;
 9     
10     private Integer requestNum = 1;
11 
12     /**
13      * 模拟本地负载均衡
14      * @return
15      */
16     @RequestMapping("/loadBalancing")
17     public String loadBalancing() {
18         
19         List<ServiceInstance> serviceList = discoveryClient.getInstances("zk-consumer");
20         if(serviceList == null || serviceList.size() == 0) {
21             return null;
22         }
23         int index = requestNum % serviceList.size();
24         requestNum++;
25         
26         return serviceList.get(index).getUri().toString();
27     }
28     
29     @RequestMapping("/zk/consumer")
30     public String consulConsumer() {
31 
32         String produceUrl = "http://zk-produce/zk/produce";
33         
34         
35         String reusltProduce = restTemplate.getForObject(produceUrl, String.class);
36         
37         return reusltProduce;
38     }
39     
40     @RequestMapping("/discoveryClient")
41     public List<ServiceInstance> discoveryClient() {
42         
43         List<ServiceInstance> instances = discoveryClient.getInstances("zk-consumer");
44         for (ServiceInstance serviceInstance : instances) {
45             System.out.println("url:" + serviceInstance.getUri());
46         }
47         
48         return instances;
49     }
50 }

  2.RestTemplate方法

  •  getForEntity:第一个参数请求的url(这里最好用服务实例的名称调用,不要用ip,可以实现负载均衡),第二个参数body的返回类型,第三个参数是请求的参数。

 

 1 @RequestMapping("/getForEntity")
 2     public ResponseEntity<String> getForEntity(String name) {
 3         
 4         Map<String, String> paramMap = new HashMap<>();
 5         String produceUrl = "http://zk-produce/zk/produce?name={name}";
 6         
 7         paramMap.put("name", name);
 8         ResponseEntity<String> resultEntity = restTemplate.getForEntity(produceUrl, String.class, paramMap);
 9         
10         return resultEntity;
11     }
  • getForObjece:对上面的方法再次包装,此方法只返回消息体重的内容。
 1 @RequestMapping("/zk/consumer")
 2     public String consulConsumer() {
 3 
 4         String produceUrl = "http://zk-produce/zk/produce";
 5         
 6         
 7         String reusltProduce = restTemplate.getForObject(produceUrl, String.class);
 8         
 9         return reusltProduce;
10     }
  • post请求:postForEntity和postForObject与上面get请求方式一致。

 

springcloud-eureka

原文:https://www.cnblogs.com/0ziyu0/p/10661344.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!