摘要
我们不管在进行分布式开发还是微服务开发,都需要接触一个组件,那就是服务治理中心,必须有一个组件为你提供和发现服务的功能,注册中心可以由zookeeper、reids、eureka等框架担任,因为我们这个系列主讲springcloud,所以本篇文章主要介绍eureka组件,后面也会论述这几种注册中心的区别。
eureka简介
spring cloud eureka是 基于netflix eureka的二次封装,主要负责实现微服务架构中的服务治理功能,springcloud eureka是基于http协议上的rest通信方式,并且提供了对应的客户端组件,能够非常方便的进行服务治理。服务治理必须要要有一个注册中心,除了使用eureka作为注册中心,还可以使用zookeeper作为注册中心,阿里开源的dubbo框架就可以支持zookeeper作为注册中心,使用过dubbo的人,都知道dubbo除了提供zookeeper作为注册中心,还可以支持redis等框架作为注册中心。刚接触微服务或者分布式的人可能还不知道什么叫做服务注册中心,我简单给大家描述下,大家可以看下这张图
上图描述注册中心的主要功能,生产者既可以提供服务又可以作为消费者去向注册中心请求服务。如果大家对注册中心还不是很了解的话,那就看下图:
eureka实战
开发工具:IDEA ,jdk版本:1.8 maven 3.5.4
服务注册中心开发
1.创建一个空项目,命名为springcloud-blog
打开项目后,添加新的模块
2.添加新模块
一直点击next,创建项目完成
3.添加依赖,为了保证后面操作一致性,建议复制以下依赖到pom文件中
org.springframework.bootspring-boot-starter-parent2.0.6.RELEASE<!-- lookup parent from repository -->1.8Finchley.SR2org.springframework.cloudspring-cloud-starter-netflix-eureka-serverorg.springframework.bootspring-boot-starter-securityorg.projectlomboklomboktrueorg.springframework.bootspring-boot-starter-testtestorg.junit.vintagejunit-vintage-engineorg.springframework.cloudspring-cloud-dependencies${spring-cloud.version}pomimport
4.开启eureka服务治理功能
添加@EnableEurekaServe注解开启
@SpringBootApplication
//开启服务治理功能
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
5.集成security框架,实现eureka安全认证
添加如下配置类
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
6.编辑配置文件
默认使用idea 创建的springboot项目,生成的配置文件是application.properties,建议使用yml格式,更加简洁明了,直接修改后缀名application.yml
将如下内容贴入
spring:
application:
# 服务名
name: eureka-server
# security安全认证配置
security:
user:
name: yangle
password: 123
server:
port: 8761
eureka:
client:
# 该应用为注册中心,不需要向注册中心注册自己
register-with-eureka: false
# 关闭检索服务的功能,只需要维护服务
fetch-registry: false
7.运行main方法,启动eureka
8.启动后test里面会报错
我们把这一行删除,然后重新导test包即可
9.项目启动后,访问http://localhost:8761/,输入用户名和密码 yangle 123
看到上面的页面,代表eureka已经启动成功,接下来我们开发服务生产者
服务生产者开发
1.创建springboot项目
项目建好之后发现右下角有提示点击show,后续就可以方便启动springboot项目了
2.复制依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<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>
3.开启服务发现功能,编辑application文件,添加
@EnableDiscoveryClient
@SpringBootApplication
//开启服务发现功能
@EnableDiscoveryClient
public class EurekaClientProducterApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProducterApplication.class, args);
}
}
4.和前面一样,更改配置文件后缀名为yml,并复制以下内容
spring:
application:
name: eureka-client-order-service
server:
port: 8081
eureka:
client:
serviceUrl:
# 指定注册中心
defaultZone: http://yangle:123@localhost:8761/eureka
instance:
#可选
preferIpAddress: true
#实例ID支持自定义,可选
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
5.添加一个订单获取服务
@RestController
public class OrderService {
@RequestMapping("getOrder")
public String getOrder(){
return "{code:0,data:{}}";
}
}
6.我们启动下这个项目,看看是否正常启动http://localhost:8081/getOrder
我们重新打开http://localhost:8761/,会看到生产者已经注册到注册中心里面了
服务消费者开发
,和生产者一样,只需要将项目名改为eureka-client-consumer
1.修改yml文件
spring:
application:
name: eureka-client-order-consumer-service
server:
port: 8082
eureka:
client:
serviceUrl:
defaultZone: http://yangle:123@localhost:8761/eureka
instance:
preferIpAddress: true
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
2.将restTemplate注入到容器中,SpringRestTemplate是Spring 提供的用于访问 Rest 服务的客端, RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率,所以很多客户端比如Android或者第三方服务商都是使用RestTemplate 请求 restful服务
@SpringBootApplication
public class EurekaClientConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerApplication.class, args);
}
@Bean(name = "restTemplate")
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
3.添加一个接口去调用生产者提供的服务
@RestController
public class OrderConsumerService {
@Autowired
@Qualifier("restTemplate")
private RestTemplate restTemplate;
@RequestMapping("getOrder")
public String getOrder(){
//IP替换为自己的本地IP
return restTemplate.getForObject("http://IP:8081/getOrder",String.class);
}
}
这里使用的就是resttemplate去调用这个服务,这种调用方式虽然简单,但是有一个弊端就是当我们这个服务进行集群部署的时候,这一块就很难快进行负载均衡了,因为这里指定了调用哪个节点的服务,当然这一块springcloud也为我们想到了
4.使用注解@LoadBalanced实现通过服务名去调用,修改配置内容
@SpringBootApplication
public class EurekaClientConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerApplication.class, args);
}
@Bean(name = "restTemplate")
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Bean(name = "restTemplate2")
@LoadBalanced
public RestTemplate getRestTemplate2() {
return new RestTemplate();
}
}
5.添加实现了loadbalence功能的resttemplate
@RestController
public class OrderConsumerService {
@Autowired
@Qualifier("restTemplate")
private RestTemplate restTemplate;
@Autowired
@Qualifier("restTemplate2")
private RestTemplate restTemplate2;
@RequestMapping("getOrder")
public String getOrder(){
return restTemplate.getForObject("http://192.168.31.168:8081/getOrder",String.class);
}
// 实现负载均衡的服务,不需要指定节点,只需要指定使用的服务名称
@RequestMapping("getOrderForLoadBalence")
public String getOrderForLoadBalence(){
return restTemplate2.getForObject("http://eureka-client-order-service/getOrder",String.class);
}
}
6.启动项目后,再次访问新接口,看看是否访问成功
7.查看eureka面板。看到消费者也注册进来了
实现高可用的eureka
实现原理:通过添加一个新的注册中心,然后让他们相互注册,实现高可用
复制eureka-server项目,更名为eureka-server-slave
修改eureka-server-slave的配置文件
spring:
application:
name: eureka-server
security:
user:
name: yangle
password: 123
server:
port: 8762
eureka:
client:
serviceUrl:
defaultZone: http://yangle:123@localhost:8761/eureka
修改eureka-server的配置文件
spring:
application:
name: eureka-server
security:
user:
name: yangle
password: 123
server:
port: 8761
eureka:
client:
serviceUrl:
defaultZone: http://yangle:123@localhost:8762/eureka
修改producter和consumer的配置文件
生产者
spring:
application:
name: eureka-client-order-service
server:
port: 8081
eureka:
client:
serviceUrl:
defaultZone: http://yangle:123@localhost:8761/eureka,http://yangle:123@localhost:8762/eureka
instance:
preferIpAddress: true
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
消费者
spring:
application:
name: eureka-client-order-consumer-service
server:
port: 8082
eureka:
client:
serviceUrl:
defaultZone: http://yangle:123@localhost:8761/eureka,http://yangle:123@localhost:8762/eureka
instance:
preferIpAddress: true
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
添加新的注册中心地址,同时向两个注册中心注册服务
重新启动,验证功能
!!!实战功能到此结束,接下来给自己加点理论知识
zookeeper与eureka的区别
因为在分布式领域中有个著名的CAP理论,三者不可能同时存在,要么AP,要么CP,CAP分别代表什么呢
C:一致性
A:可用性
P:分区容错性
现在来说说为什么CAP不能同时共存呢,因为要保证数据的一致性的话,肯定需要在数据同步到其他节点的时候,将数据锁住,停止产生新的数据,这时候将会拒绝新的请求或者让使用者一直处于阻塞等待的状态,只有在同步完成之后才会释放,接收或处理新的请求,这就会造成服务的不可用性,同样的如果保证服务的可用性,那就在数据同步的时候不能进行锁操作,这与数据一致性的必要条件冲突,这也就是CA不能互溶的元婴,有人会说那P呢,P是必须存在的,因为如果是集群那么P就必须存在。
再来说下zookeeper与eureka区别,zookeeper是基于CP上的,舍弃了A,他经常与DUBBO结合,EUREKA强调AP。舍弃了一致性
内容引自:https://blog.csdn.net/alan_gaohaodong/article/details/82899413
Zookeeper保证CP原则:
1.1当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,
但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求高于一致性。
但是zk会出现这一种情况,当master节点因为网络故障与其他节点失去联系时,剩余注册
功能就会重新进行leader选举看。问题在于,选举leader的时间太长,30~120s,且选举期间
整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题
使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的
选举时间导致的注册长期不可用是不能容忍的。
1.2Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等
的,几个节点挂掉不会影响正常节点的工作,剩余节点依然可以提供注册和查询服务。
而Eureka的客户端在向某个Eureka注册或者如果发现链接失败时,则会自动切换至其他节点,
只要有一台Eureka还在,就能保证注册服务可用(保证可用),只不过查到的信息可能不是
最新的(不保证一致性)。除此以外,Eureka还有一种自我保护机制,如果在15分钟内超过85%
的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现
一下几种情况:
(1)Eureka不在从注册列表中移除因为长时间没收到心跳而应该过期的服务
(2)Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上
(保证当前节点依然可用)
(3)当网络稳定时,当前实例新的注册信息会被同步到其他节点中
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zk那样
是整个注册服务瘫痪。
有关eureka面试题及解答
1.介绍下CAP
答案如上
2.EUREKA与zookeeper区别
答案如上
总结
通过本章介绍,了解了什么是注册中心,已经能够提供注册中心功能的框架,紧接着介绍了eureka的入门使用及如何保证eureka注册中心的高可用,最后讨论了zookeeper与eureka的区别和面试中常见的有关eureka的问题,后面继续讲解springcloud的相关知识,下一节会介绍如何实现客户端的负载均衡。
欢迎大家关注我的公众号,回复eureka,获取本章源码,回复“资料领取”,获取人工智能、大数据等更多学习视频资料,如有侵权,请联系作者立即删除!
网友评论