Spring Cloud(2):服务发现(Eureka)
Spring Cloud Eureka是Spring Cloud Netflix项目下的一个模块,作用是服务的注册和发现,并实现服务治理。它有一个(或一组,以实现高可用)服务注册中心(eureka server)并提供服务注册功能,所有的应用程序将作为服务提供方(eureka client)向eureka server注册服务,当应用程序之间相互调用时,不再通过IP地址调用,将通过eureka server,使用注册的service id来调用。
下面,分别从5个方面来讲Eureka:Eureka Server,Eureka Client,Peer Awareness,Securing The Eureka Server,Discovery Client。
(1)搭建Eureka Server
首先,创建一个SpringBoot Web Aplication,在pom.xml中加入spring-cloud-starter-netflix-eureka-server包。这里使用的是Spring Boot 2.2.5和Spring Cloud Hoxton.SR3。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<!-- Spring cloud starter: netflix-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
其次,在启动类ServerEurekaApplication中加入@EnableEurekaServer注解。
@SpringBootApplication
@EnableEurekaServer
public class ServerEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(ServerEurekaApplication.class, args);
}
}
最后,在配置文件中配置Eureka信息。
bootstrap.yml
spring:
application:
name: server-eureka
application.yml
## Server info
server:
port:
servlet:
context-path: /server-eureka ## Eureka info
eureka:
instance:
hostname: localhost
# You need to change these, even for an Actuator application if you use a non-default context path or servlet path
# https://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#_status_page_and_health_indicator
statusPageUrlPath: ${server.servlet.context-path}/actuator/info
healthCheckUrlPath: ${server.servlet.context-path}/actuator/health
client:
# 程序启动时不要通过Eureka注册服务,因为它本身就是Eureka服务
registerWithEureka: false
# 不会在本地缓存注册表信息
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/server-eureka/eureka/
# Eureka不会马上通知任何注册它的服务,默认情况下会等待5min。本地测试时应该注释掉此行,以加快程序运行
# 每次服务注册需要30s的时间才能显示在Eureka服务中,因为Eureka需要接收3此心跳包,每次间隔10s,然后才能使用这个服务。
#server:
# waitTimeInMsWhenSyncEmpty: 5
server:
waitTimeInMsWhenSyncEmpty:
(2)搭建Eureka Client
首先,创建一个SpringBoot Web Aplication,在pom.xml中加入spring-cloud-starter-netflix-eureka-client包。
<!-- Spring cloud starter: netflix-eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
然后,在配置文件中配置Eureka信息。
## Server Info
server:
port:
servlet:
context-path: /app-web ## Eureka info
eureka:
instance:
# You need to change these, even for an Actuator application if you use a non-default context path or servlet path
# https://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#_status_page_and_health_indicator
statusPageUrlPath: ${server.servlet.context-path}/actuator/info
healthCheckUrlPath: ${server.servlet.context-path}/actuator/health
# 注册服务的IP而不是服务器名称
# preferIpAddress: true
client:
# 向Eureka注册服务(default is true)
registerWithEureka: true
# 拉取注册表的本地副本(default is true)
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:10000/server-eureka/eureka/
[注1] preferIpAddress:在默认情况下,Eureka注册服务使用了主机名与外界联系,这种方式在服务器环境中是OK的,因为通过DNS可以解析成IP地址。但是,在基于容器的部署环境中(如Docker),主机名是随机生成的,且并没有DNS记录。将eureka.instance.preferIpAddress设置为true,当应用程序向eureka注册时,它使用其IP地址而不是其主机名。
如果设置eureka.instance.prefer-ip-address为false时,那么注册到Eureka中的IP地址就是本机的IP地址。如果设置了true并且也设置了eureka.instance.ip-address那么就将此ip地址注册到Eureka中。那么调用的时候,发送的请求目的地就是此Ip地址。
参考:
https://www.jianshu.com/p/886947b52cb4
[注2] 从Spring Cloud Edgware开始,@EnableDiscoveryClient或@EnableEurekaClient可省略。只需加上相关依赖,并进行相应配置,即可将微服务注册到服务发现组件上。Spring Cloud中的Discovery Service有多种实现,比如:eureka,consul,zookeeper。
- @EnableDiscoveryClient 注解是基于spring-cloud-commons依赖,并且在classpath中实现
- @EnableEurekaClient 注解是基于spring-cloud-netflix依赖,只能为eureka作用
如果你的classpath中添加了eureka,则它们的作用是一样的。
(3)Peer Awareness(高可用的Eureka集群)
假设我们现在有3台Eureka Server,IP地址分别为:192.168.0.1,192.168.0.2,192.168.0.3。配置文件修改如下:
application-peer1.yml
## Eureka info
eureka:
instance:
# http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#spring-cloud-eureka-server-peer-awareness
hostname: 192.168.0.1
client:
# 需要修改下面两个配置,让注册中心可以向另外一个注册中心注册服务,以实现高可用
registerWithEureka: true
fetchRegistry: true
# 向另2个Eureka Server注册自己
serviceUrl:
defaultZone: http://192.168.0.2:10000/server-eureka/eureka/,http://192.168.0.3:10000/server-eureka/eureka/
application-peer2.yml
eureka:
instance:
hostname: 192.168.0.2
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://192.168.0.1:10000/server-eureka/eureka/,http://192.168.0.3:10000/server-eureka/eureka/
application-peer3.yml
eureka:
instance:
hostname: 192.168.0.3
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://192.168.0.1:10000/server-eureka/eureka/,http://192.168.0.2:10000/server-eureka/eureka/
当我们在Eureka Client中向Eureka Server注册时,需要修改配置文件如下:
eureka:
client:
serviceUrl:
defaultZone: http://192.168.0.1:10000/server-eureka/eureka/,http://192.168.0.2:10000/server-eureka/eureka/,http://192.168.0.3:10000/server-eureka/eureka/
(4)使用Spring Security保护Eureka Server
首先,在pom.xml中加入spring-cloud-starter-netflix-eureka-client包。
<!-- Spring cloud starter: security -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
然后,添加一个user和password用于登录Eureka Server自带的页面:http://{host}:{port}/server-eureka。值得注意的是,需要disable'/eureka/**'端点的csrf()。
@EnableWebSecurity
public class ServerEurekaWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
} @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//@formatter:off
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.withUser("eureka-user").password("{bcrypt}" + encoder.encode("eureka-user")).roles("USER");
//@formatter:on
} @Override
protected void configure(HttpSecurity http) throws Exception {
// By default when Spring Security is on the classpath,
// it will require that a valid CSRF token be sent with every request to the app.
// Eureka clients will not generally possess a valid cross site request forgery (CSRF) token,
// you will need to disable this requirement for the /eureka/** endpoints.
// https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.1.2.RELEASE/single/spring-cloud-netflix.html#_securing_the_eureka_server
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}
最后,所有向Eureka Server注册的URL都要改成这样的形式:http://user:password@localhost:8761/eureka。
上面(3)中Eureka Server集群中的相互注册:
eureka:
username: eureka-user
password: '{cipher}72cd0bdd18c6928b025e9e5dfa94cce539b555c4b3364590c689df3532fa69bc'
client:
serviceUrl:
defaultZone: http://${eureka.username}:${eureka.password}@192.168.0.2:10000/server-eureka/eureka/,http://${eureka.username}:${eureka.password}@192.168.0.3:10000/server-eureka/eureka/
上面(3)中Eureka Client中的注册:
eureka:
username: eureka-user
password: '{cipher}72cd0bdd18c6928b025e9e5dfa94cce539b555c4b3364590c689df3532fa69bc'
client:
serviceUrl:
defaultZone: http://${eureka.username}:${eureka.password}@192.168.0.1:10000/server-eureka/eureka/,http://${eureka.username}:${eureka.password}@192.168.0.2:10000/server-eureka/eureka/,http://${eureka.username}:${eureka.password}@192.168.0.3:10000/server-eureka/eureka/
[注] 上面密码使用JCE(Java Cryptography Extension)的对称加密,这部分可以看 Spring Cloud(4):配置服务(Config)。
(5)在Eureka Client中使用Discovery Client来发现并调用其他Client服务
一个微服务架构中会有多个Eureka Client,当它们向Eureka Server注册后,就可以通过下面2种方法相互调用:
1. 使用EurekaClient(DiscoveryClient)
@Autowired
private EurekaClient discoveryClient; public String serviceUrl() {
InstanceInfo instance = discoveryClient.getNextServerFromEureka("app-name", false);
String path = String.format("http://%s:%s/aaa/bbb", instance.getHostName(), instance.getPort());
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(path, HttpMethod.GET, null, String.class);
return response.getBody();
}
2. 使用带有Ribbon功能的LoadBalancerClient(负载均衡)
@Autowired
private LoadBalancerClient loadBalancer; public String serviceUrl() {
ServiceInstance instance = loadBalancer.choose("app-db");
String path = String.format("http://%s:%s/aaa/bbb", instance.getHost(), instance.getPort());
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(path, HttpMethod.GET, null, String.class);
return response.getBody();
}
Hoxton.SR3
Spring Cloud(2):服务发现(Eureka)的更多相关文章
- Spring cloud 微服务架构 Eureka篇
1 服务发现 ## 关于服务发现 在微服务架构中,服务发现(Service Discovery)是关键原则之一.手动配置每个客户端或某种形式的约定是很难做的,并且很脆弱.Spring Cloud提供了 ...
- Spring Cloud 2-Eureka服务发现注册(一)
Spring Cloud Eureka 1.服务端配置 pom.xml application.yml Application.java 2.客户端配置 pom.xml application.ym ...
- 二、spring cloud 注册与发现eureka注册中心
基于2.0 Greenwich高可用eureka注册中心搭建 一.单机版 新建MAVEN父工程demo-parent 删掉src pom.xml <packaging>pom</pa ...
- Spring Cloud|高可用的Eureka集群服务
Eureka,作为spring cloud的服务发现与注册中心,在整个的微服务体系中,处于核心位置.单一的eureka服务,显然不能满足高可用的实际生产环境,这就要求我们配置一个能够应对各种突发情况, ...
- 用ZooKeeper做为注册中心搭建基于Spring Cloud实现服务注册与发现
前提: 先安装好ZooKeeper的环境,搭建参考:http://www.cnblogs.com/EasonJim/p/7482961.html 说明: 可以再简单的理解为有两方协作,一个是服务提供这 ...
- Spring Cloud 微服务的那点事
什么是微服务 微服务的概念源于2014年3月Martin Fowler所写的一篇文章“Microservices”. 微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调 ...
- spring cloud 学习(二)关于 Eureka 的学习笔记
关于 Eureka 的学习笔记 个人博客地址 : https://zggdczfr.cn/ ,欢迎光临~ 前言 Eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务.Sprin ...
- Spring Cloud 微服务一:Consul注册中心
Consul介绍 Consul is a service mesh solution providing a full featured control plane with service disc ...
- Spring Cloud (1) 服务的注册与发现(Eureka)
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...
- Spring cloud实现服务注册及发现
服务注册与发现对于微服务系统来说非常重要.有了服务发现与注册,你就不需要整天改服务调用的配置文件了,你只需要使用服务的标识符,就可以访问到服务. 本文属于<7天学会spring cloud系列& ...
随机推荐
- JDK的收费问题
关于JDK是否收费,我也有过疑问,查了一些资料,就在这里做一个简要的说明. 首先要明白JDK的发布模型.两年多以前,2017年9月21日,伴随着JDK9的发布,JDK就开启了新的发布模式(如下图所示) ...
- Aizu - 1383 Pizza Delivery (最短路图+DAG上的割边)
题意:给出一张有向图,每条边有长度,对于每条边,你要回答将该边的方向取反后,从起点到终点的最短距离是增加or减小or不变. 首先求出起点到所有点的最短距离和所有点到终点的最短距离(两次DIjkstra ...
- Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化
引言 在数据库存在外键的其情况下,使用select_related()和prefetch_related()很大程度上减少对数据库的请求次数以提高性能 1.实例准备 模型: from django.d ...
- canvas drawImage图片不显示问题
初次学习canvas,用来做笔记记录下遇到的问题及解决方案 这里是要将一张图片写到canvas里,按照网上搜索,初写了段代码,可是却没显示,以为是路径问题,不能跨域名使用,后来改为相对路径后,仍然无效 ...
- 长春理工大学第十四届程序设计竞赛A Rubbish——并查集&&联通块
题目 链接 题意:在 $10^5 \times 10^5$ 的大网格上,给出 $n$ 的格点的坐标,求联通块数(上下左右及对角线都认为相邻) 分析 DFS需要遍历网格的每个格点,可能会超时? 初始化时 ...
- oracle split函数
PL/SQL 中没有split函数,需要自己写. 代码: ); --创建一个 type ,如果为了使split函数具有通用性,请将其size 设大些. --创建function create or r ...
- jsp前台输入框不输入值,后台怎么取出整型?
当前台输入框限定整型,后台取值就会出现很多问题. eg: Integer.parseInt(request.getParameter("uno"));当前台的文本框不输入值,直接点 ...
- PHP mysqli_kill() 函数
定义和用法 mysqli_kill() 函数请求服务器杀死一个由 processid 参数指定的 MySQL 线程. 语法 mysqli_kill(connection,processid); 实 ...
- 洛谷P2110 欢总喊楼记
洛谷题目链接 乱搞qwq 我们其实可以找规律,对于每个数$x$,我们先求出从$1$~$x$中有多少符合条件的,记为$sum[x]$,那么类似于前缀和,答案自然就是$sum[r]-sum[l-1]$了 ...
- 51 Nod 1110距离之和最小V3
1110 距离之和最小 V3 1 秒 131,072 KB 40 分 4 级题 X轴上有N个点,每个点除了包括一个位置数据X[i],还包括一个权值W[i].点P到点P[i]的带权距离 = 实际距离 * ...