Spring Cloud-Eureka实现服务的注册与发现(二)
在Spring Cloud中是使用Eureka来实现服务的注册与发现的
请勿使用eureka2.x 用于生产 2.x已经停止开发了 使用1.x 最新版是1.9 我这里demo是使用1.9 详情:https://github.com/Netflix/eureka/wiki
项目骨架搭建
创建父工程
1.创建一个父工程 实现版本的统一管理 以及子项目的管理


然后下一步下一步
创建子工程



在对应的tab 勾选web和EurekaServer 创建项目后会自动生成pom依赖 注意右上角cloud版本
将eureka子工程的paren 节点改为指向父工程 这的各个节点需要改为 你的对应父工程的节点描述
<parent>
<groupId>com.liqiang</groupId>
<artifactId>spring-cloud-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
将工程的在父工程创建节点 并删除子工程的 没有的话就不管
<!--版本号的统一管理。 子类项目没有配置版本号的时候 会从子往上找 找到 dependencyManagement 找到对应的版本-->
<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>
父工程model配置上eureka子工程
<modules>
<module>spring-cloud-eureka</module>
</modules>

最后将父工程的Src目录删除 这样我们项目的基础骨架就搭建好了 可以进行eureka的相关配置了
个人习惯 喜欢用yml配置 所以讲resource下面的application.properties 后缀改为yml

最后将parent pom文件的<packaging>jar</packaging> 改为<packaging>pom</packaging>
然后执行parent安装
配置Eureka服务端
1.增加pom依赖并在Application类添加@EnableEurekaServer注解 开启服务注册功能
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
@SpringBootApplication
@EnableEurekaServer //开启服务注册的功能
public class SpringCloudEurekaApplication { public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaApplication.class, args);
}
}
2.配置application.yml
server:
port: 1111 eureka:
instance:
hostname: localhost #主机名
client:
registerWithEureka: false #不注册自己 只维护服务 #集群情况下 是需要改成true 的因为 集群是注册中心 相互注册自己 同步服务
fetchRegistry: false #是否开启从 Eureka-Server 获取注册信息。默认值:true 集群情况下需要为true的 因为 会在别的注册中心 获取服务
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #集群情况配置多注册中心,号隔开 单机情况下 不配置也没关系
3.访问http://127.0.0.1:1111

表示注册中心搭建成功。。registerWithEureka 我们设置了false 表示不注册 自己 我们可以尝试改成true 则可以看到 服务里面会出现服务
配置服务提供者
1.跟创建注册中心一样 创建一个名为provider的项目 pom配置文件 跟provider一致
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2.配置 application.yml配置文件
spring:
application:
name: provider #服务名字
server:
port: 8081
eureka:
instance:
hostname: localhost #当前实例的主机名字
client:
serviceUrl:
defaultZone: http://127.0.0.1:1111/eureka/ #注册中心地址
3. @EnableDiscoveryClient 开启服务注册到注册中心的功能
@SpringBootApplication
@EnableDiscoveryClient //开启将服务注册到注册中心
public class SpringCloudProviderApplication { public static void main(String[] args) {
SpringApplication.run(SpringCloudProviderApplication.class, args);
}
}
4.创建对一个对外暴露的服务(注意 必须在application启动类所在目录或者下级目录)
@RestController
public class HelloServerContorrler {
@RequestMapping(value = "/hello")
public String hello(){
return "hello";
}
}
5.启动eureka 再启动provider 可以发现服务已经注册到注册中心

服务消费者配置
跟上面一样创建一个consumer

pom配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--rabbon客户端的负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
启动类配置
@SpringBootApplication
@EnableDiscoveryClient //开启服务发现
public class ConsumerApplication { public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
//LoadBalanced 通过代理RestTemplate 实现客户端负载均衡的能力
@LoadBalanced
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
}
yml配置
spring:
application:
name: consumer
server:
port: 9001
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:1111/eureka #注册中心地址
调用服务
@Controller
public class HelloContorller {
//applicaton启动类配置的@LoadBalanced 的代理对象
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/hello")
@ResponseBody
public String hell(){
//PROVIDER需要大写 这里没有配置物理地址 而是服务名 是去服务集群 获得集群服务地址 来实现负载均衡
return restTemplate.getForEntity("http://PROVIDER/hello",String.class).getBody();
}
}
访问http://127.0.0.1:9001/hello

注册中心集群
1.配置host文件 模拟域名映射ip 比如我们通过http://peer1:8081/user 访问 实际上是访问peer1对应的ip 如http://127.0.0.1:8081/user
host文件在哪儿自行百度
127.0.0.1 peer1
127.0.0.1 peer2

2.copy2个配置文件 端口改为不一致

配置文件1
server:
port: 1111
eureka:
instance:
hostname: localhost #主机名
client:
registerWithEureka: true #将自己注册到 集群中的其他注册中心
fetchRegistry: true #从注册中心同步服务。
serviceUrl:
defaultZone: http://peer1:1112/eureka/ #集群汇总的其他注册中心地址 多个,号隔开
spring:
application:
name: eureka
配置文件2
server:
port: 1112
eureka:
instance:
hostname: localhost #主机名
client:
registerWithEureka: true #将自己注册到 集群中的其他注册中心
fetchRegistry: true #从注册中心同步服务。
serviceUrl:
defaultZone: http://peer1:1111/eureka/ #集群汇总的其他注册中心地址 多个,号隔开
spring:
application:
name: eureka
注册中心集群 是根据注册中心之间相互注册和相互订阅同步服务实现的 可以通过上面配置看出来
4.provider和cusumer的注册中心地址指向集群的注册中心所有
spring:
application:
name: consumer
server:
port: 9001 eureka:
client:
serviceUrl:
defaultZone: http://peer1:1111/eureka,http://peer2:1112/eureka
spring:
application:
name: provider #服务名字
server:
port: 8081
eureka:
instance:
hostname: localhost #当前实例的主机名字
client:
serviceUrl:
defaultZone: http://peer1:1111/eureka,http://peer2:1112/eureka #注册中心地址
3.打包安装 手动执行jar包 并分别指定配置文件路径替换成本地打包的路径
java -jar /Users/liqiang/Desktop/java开发环境/javadom/spring-cloud-parent/spring-cloud-eureka/target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar /Users/liqiang/Desktop/java开发环境/javadom/spring-cloud-parent/spring-cloud-eureka/target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
5.启动provider
6.启动cusumer

高可用集群的注册中心就搭建好了
eureka逻辑图

默认服务提供者启动会注册服务到注册中心的双层map 第一层key为服务名 第二层为key为实例信息 同时维持一个心跳方式注册中心认为自己挂了将自己从服务列表剔除
不知道怎么测试 正常关闭的话会通过REST通知到服务注册中心 注册中心将服务状态改为down 再通知下去
客户端配置:
# 多久未收到心跳,剔除instance 要比心跳时间大
eureka.instance.lease-expiration-duration-in-seconds:30
# 心跳时间间隔
eureka.instance.lease-renewal-interval-in-seconds: 5
服务端配置:
eureka.instance.eviction-interval-timer-in-ms: 5000 多久去剔除一次指定时间没有续约的服务
消费者启动会拉取注册中心服务。为了性能 eurekaServer会维护30秒的服务清单 该清单默认30秒更新一次 可以通过以下配置
eureka.client.registry-fetch-interval-seconds=30 确保开启 eureka.client.fetchRegistry: false #是否开启从 Eureka-Server 获取注册信息。默认值:true
服务保护机制

前面说了 注册中心是通过 服务提供者维护的心跳来控制服务是否有效 当15分钟内 心跳失败的比例在85%会开启保护机制 这个时候服务就不会因为续约过期而下线(个人觉得是为了防止 注册中心 网络出现问题 导致服务提供者通过心跳请求不能成功续约) 保护机制会导致客户端拿到 无效的服务 所以需要客户端启用启用重试和断路器机制
可以通过eureka.instance.enable-self-preservation=false 关闭保护机制(不建议开启 本地开发可以开启)
Eureka初始化过程
1.配置信息启动都会封装到EurekaClientConfig
2.com.netflix.discovery.DiscoveryClient 根据EurekaClientConfig会初始化3个定时任务 分别服务注册 服务获取 服务续约(心跳) 三个定时任务都是根据rest接口而来的
通过源码
com.netflix.discovery.DiscoveryClient的构造函数可以发现初始化定时任务的方法
private void initScheduledTasks() {
//是否从注册中心订阅服务对应eureka.client.registerWithEureka配置
if (clientConfig.shouldFetchRegistry()) {
//多久去注册中心拉取一次服务对应eureka.client.registry-fetch-interval-seconds
int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
//服务拉取失败的重试时间系数
int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
scheduler.schedule(
new TimedSupervisorTask(
"cacheRefresh",
scheduler,
cacheRefreshExecutor,
registryFetchIntervalSeconds,
TimeUnit.SECONDS,
expBackOffBound,
new DiscoveryClient.CacheRefreshThread()
),
registryFetchIntervalSeconds, TimeUnit.SECONDS);
}
//是否对注册中心注册服务 对应eureka.client.fetchRegistry
if (clientConfig.shouldRegisterWithEureka()) {
//心跳间隔时间 对应eureka.instance.lease-renewal-interval-in-seconds
int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
//心跳超时重试的系数对应
int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound();
logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs);
// Heartbeat timer
scheduler.schedule(
new TimedSupervisorTask(
"heartbeat",
scheduler,
heartbeatExecutor,
renewalIntervalInSecs,
TimeUnit.SECONDS,
expBackOffBound,
new DiscoveryClient.HeartbeatThread()
),
renewalIntervalInSecs, TimeUnit.SECONDS);
// 服务注册定时任务
instanceInfoReplicator = new InstanceInfoReplicator(
this,
instanceInfo,
clientConfig.getInstanceInfoReplicationIntervalSeconds(),
2); // burstSize
statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {
@Override
public String getId() {
return "statusChangeListener";
}
@Override
public void notify(StatusChangeEvent statusChangeEvent) {
if (InstanceInfo.InstanceStatus.DOWN == statusChangeEvent.getStatus() ||
InstanceInfo.InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) {
// log at warn level if DOWN was involved
logger.warn("Saw local status change event {}", statusChangeEvent);
} else {
logger.info("Saw local status change event {}", statusChangeEvent);
}
instanceInfoReplicator.onDemandUpdate();
}
};
if (clientConfig.shouldOnDemandUpdateStatusChange()) {
applicationInfoManager.registerStatusChangeListener(statusChangeListener);
}
instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
} else {
logger.info("Not registering with Eureka server per configuration");
}
}
配置参考
https://blog.csdn.net/cvntopuyef/article/details/78477724
Instance配置
服务注册会向注册中心发送一些用于描述自己的的元数据信息比如 服务名称、 实例名称、 实例IP、 实例端口等
在使用 Spring CloudEureka的时候, 所有的配置信息都通过org.springframework.cloud.netflix.eureka.EurekalnstianceConfigBean进行加载
但在真正进行服 务注册的时候, 还是会包装成com.netflix.appinfo.Instiancelnfo
可以通过eureka.instance.metadataMap.<key>=<value> 来进行自定发送数据
eureka.instance.instanceid 指定服务实例id 默认主机名+端口
指定服务info和heath端点路径 heath用于服务更新服务状态 down up info用于注册中心点击服务访问信息 保证这2类不要404 默认一般不用修改 当上下文修改 可以通过以下配置指定需要引入
spring-boot-starter-actuator模块
management.context-path=/hello
eureka.instance.statusPageUrlPath=${management.context-path}/info
eureka.instance.healthCheckUrlPath=${management.context-path}/health
instance其他配置

Spring Cloud-Eureka实现服务的注册与发现(二)的更多相关文章
- Spring Cloud Eureka 实现服务注册与发现
微服务 是一种架构模式,跟具体的语言实现无关,微服务架构将业务逻辑分散到了各个服务当中,服务间通过网络层进行通信共同协作:这样一个应用就可以划分为多个服务单独来维护发布.构建一个可靠微服务系统是需要具 ...
- 服务注册发现Eureka之一:Spring Cloud Eureka的服务注册与发现
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...
- Spring Cloud Eureka Server高可用注册服务中心的配置
前言 Eureka 作为一个云端负载均衡,本身是一个基于REST的服务,在 Spring Cloud 中用于发现和注册服务. 那么当成千上万个微服务注册到Eureka Server中的时候,Eurek ...
- Spring Cloud Eureka Server使用(注册中心)
一.Spring Cloud Eureka 基于Netflix Eureka做了二次封装 由两个组件组成 Eureka Server 注册中心, 供服务注册的服务器 Eureka Client 服务注 ...
- Spring Cloud(二):Spring Cloud Eureka Server高可用注册服务中心的配置
前言 Eureka 作为一个云端负载均衡,本身是一个基于REST的服务,在 Spring Cloud 中用于发现和注册服务. 那么当成千上万个微服务注册到Eureka Server中的时候,Eurek ...
- Spring Cloud 系列之 Alibaba Nacos 注册中心(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Alibaba Nacos 注册中心(一) 本篇文章讲解 Nacos 注册中心集群环境搭建. Nacos 集群环境搭建 ...
- Spring Cloud Eureka 之服务端自我注册
Eureka服务端实现了一种自我注册机制,涉及配置项: eureka.client.register-with-eureka spring.application.name Eureka Server ...
- Spring Cloud Eureka 5 (服务发现与消费-简单的robbin使用)
通过上述介绍,我们已经有了服务注册中心和服务提供者 下面我们来尝试构建一个服务的消费者 它要完成两个功能,发现服务和消费服务,其中发现服务由eureka客户端完成,消费服务由ribbon完成. rib ...
- 《深入理解Spring Cloud与微服务构建》学习笔记(二十)~配置中心Spring Cloud Config
本例重新创建项目,构建一个空的mavan工程. 一.Config Server 从本地读取配置文件 新建一个moudle config_server ,pom添加依赖 <dependency ...
随机推荐
- 二分查找(c & c++)
typedef int ElemType; C版本号 [递归版本号] int binSearch2(ElemType List[] ,int x,int head,int tail){ //递归版本号 ...
- jQuery - 点击图片加边框
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Coder-Strike 2014
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove? viewmode=contents by---cxlove Qualification Round 略 Ro ...
- Spring:延迟初始化
ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化.提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并 ...
- CNN tensorflow text classification CNN文本分类的例子
from:http://deeplearning.lipingyang.org/tensorflow-examples-text/ TensorFlow examples (text-based) T ...
- Codeforces Round #402 D(二分)
D. String Game ...
- Python迭代器(斐波拉切数列实例)
将一个容器通过iter()函数处理后,就变成了迭代器.迭代器有2个魔法方法__iter__.__next__,一个迭代器必须实现__iter__,这个方法实际上是返回迭代器本身(return self ...
- 5.27 indeed 第三次网测
1. 第一题, 没有看 2. 暴力枚举.每一个部分全排列, 然后求出最大的请求数. #include<bits/stdc++.h> #define pb push_back typedef ...
- Elasticsearch之批量操作bulk
1.bulk相当于数据库里的bash操作. 2.引入批量操作bulk,提高工作效率,你想啊,一批一批添加与一条一条添加,谁快? 3.bulk API可以帮助我们同时执行多个请求 4.bulk的格式: ...
- 自学Python十 爬虫实战三(美女福利续)
我又来送福利啦!!!不同于上篇文章,这次我们的爬虫采用了多线程,一直以来被所谓的分布式 多线程 爬虫 给唬的怕怕的.今天就来一发多线程爬虫吧,还能看妹子图,想想就觉得很激动!!! 依然是流程解释: ...