文章目的
本文提供给正在头疼服务注册中心和网关集成的各位朋友;
最近新换的工作,新的环境和新的工作方式,新的工作环境技术经理要求我们自己选用框架,但是他会给我们提供思路,公司准备做一个有多服务模块的项目,因为前期划分不详细,此处暂时不能称之为微服务项目,因为本人也是第一次接触微服务开发模式,不免有些手忙脚乱,但是经过一段时间的学习和验证,有些心得以及经验,分享给需要的朋友!
文章正文
一、Eureka是什么,Zuul又是什么?(What)
1.Eureka(服务注册中心)
Eureka 是 Netflix 下的服务发现框架,何为发现,发现在这里是一个动词,执行发现操作的服务发现了另外一个可以被发现的服务,既发现者和被发现者,Euerka分为两部分:
Euerka Server(发现者) 和 Eureka Client(被发现者);
那么他们能干什么呢?
在Eureka Client正常启动以后会向Eureka Server按照指定的频率发送心跳;
在Eureka Server正常启动以后可以获取查看所有心跳正常的Euerka Client;
2.Zuul(网关)
Zuul 是 一个API网关,API网关可以提供一个单独且统一的API入口用于访问内部一个或多个API。它可以将一个一直的请求通过路由的方式,映射到另外一个地址,使真实地址不可见;也可以对所有的请求进行拦截,验证,简单来说嘛就是一个统一入口,比如现在的支付宝或者微信的相关api服务一样,都有一个统一的api地址,统一的请求参数,统一的鉴权。
这里只是简单讲一下Euerka是啥东西,因为我们的重点是使用,如果小伙伴需要详细了解Euerka和Zuul请移步至以下文章:
Euerka详解
&
Zuul详解
二、为什么要使用服务注册中心,为什么要使用网关?(Why)
1.服务注册中心(Eureka)
Eureka是一种基于REST(Representational State Transfer)的服务,主要用于AWS云,用于定位服务,以实现中间层服务器的负载平衡和故障转移。我们称这个服务,Eureka Server。Eureka还提供了一个基于Java的客户端组件Eureka Client,它使得与服务的交互变得更加容易。客户端还具有内置负载均衡器,可进行基本的轮询负载均衡。
通过Eureka Client定期向Eureka Server的发送的心跳,可以判断Euerka Client的生存状态,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
2.网关(Zuul)
Zuul是Netflix开源的微服务网关,可以和Eureka、Ribbon、Hystrix等组件配合使用,Spring Cloud对Zuul进行了整合与增强,Zuul的主要功能是路由转发和过滤器。
Zuul基于JVM的路由器和服务器端负载均衡器。它的本质是一个过滤器链,同时,Zuul的规则引擎允许规则和过滤器基本上用任何JVM语言编写,内置支持Java和Groovy。这个功能,就可以实现动态路由的功能了。当需要添加某个新的对外服务时,一般上不停机更新是通过数据缓存配置或者使用Groovy进行动态路由的添加的。
三、怎样使用服务注册中心,怎样使用网关?(How)
1.服务注册中心(Eureka)
1.首先创建一个springboot项目,基础结构如下:
2.在pom.xml中引入eureka-server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.在项目启动类上加上@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
4.将resources下application.properties文件更名为application.yml,我们配置文件将统一使用yml格式:
server:
port: 8798
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
server:
# 关闭eureka服务器的自我保护功能,忽略网络分区故障
enable-self-preservation: false
# eureka服务器检测失效服务的时间间隔
eviction-interval-timer-in-ms: 5000
client:
# eureka服务器本身也是一个客户端,顾不需要注册自身
register-with-eureka: false
fetch-registry: false
至此,一个简单的Eureka Server就搭建成功了,启动项目,在浏览器中打开:
出现此页面说明Euerka启动成功,途中红字部分,是提示EuerkaServer关闭了自我保护功能
2.网关(Zuul)
1.同样,创建一个springboot项目,结构如下:
其中:
Constants包中放的是一个类,类中存放的是全局静态枚举
Filter中存放的是Zuul的四大核心过滤器 pre rout post error ;demo中有完整的说明以及详细步骤
rule中存放的是Zuul的配置类,用于自定义负载均衡策略
2.在pom.xml中添加 eureka-client依赖 和 zuul 依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
3.在项目启动类上加上@EnableEurekaClient 和 @EnableZuulProxy注解
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
4.将resources下application.properties文件更名为application.yml:
server:
port: 8086
spring:
application:
name: zuul-server
eureka:
client:
service-url:
defaultZone: http://localhost:8798/eureka/
# 表示eureka client间隔多久去拉取服务注册信息
registry-fetch-interval-seconds: 5
instance:
instance_id: ${spring.cloud.client.hostname}:${server.port}:${spring.application.name}:@project.version@
demo中有详细的网关路由,映射,屏蔽,负载的配置
至此,一个简单的 Zuul 网关就 以 Eureka Client 的形式搭建成功了,启动项目,在浏览器中查看刚刚的Eureka管理页面:
图片中我们看到在application列表中出现了 zuul-server 的服务,这就是我们刚刚搭建的网关微服务,小伙伴们肯定会问我现在搭好了网关,可是怎么用呢?别急,网关的功能体现是需要其他服务一起运作的,具体的往下看,看ribbon的使用,里边有介绍.
3.负载均衡(ribbon)
ribbon,大家都是到负责负载均衡的一个工具,在spring-cloud中,zuul 默认集成了 ribbon ,所谓负载均衡,就是当一个微服务的访问量在增大时,一个服务器已经支撑不住,这个时候就会在使用一台服务器部署一个同样的服务上去,这种情况下,用户访问这两个服务期中的任何一台服务器中的服务都可以拿到正确结果,负载均衡的作用就是根据你定义的策略或默认策略,去合理的使用这两个服务器上的相同的服务,达到资源的合理利用,具体体现如何呢,我们往下看,首先,我们需要三个或多个服务提供者(provider)来体现zuul和ribbon的具体功能体现:
1.我们先创建两个服务提供者,并各自提供一个相同的接口,但返回值不同:
创建一个springboot项目,结构如下:
引入 eureka client 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在项目启动类上加上@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient
public class Provider1stApplication {
public static void main(String[] args) {
SpringApplication.run(Provider1stApplication.class, args);
}
}
将resources下application.properties文件更名为application.yml:
server:
port: 8081
spring:
application:
name: provider1
eureka:
client:
service-url:
defaultZone: http://localhost:8798/eureka/
instance:
instance_id: ${spring.cloud.client.hostname}:${server.port}
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
在TestController中创建一个对外的接口
@RestController
@RequestMapping("/test1")
public class TestController {
@GetMapping("test1")
public Object test(){
return "123456";
}
}
到此一个服务提供者创建完毕,按照上述的方式修改一下端口和接口返回值,创建第二个服务提供者
application.yml:
server:
port: 8082
spring:
application:
name: provider1 #注意,此处的服务名称也和provider1保持一致
#eureka配置和provider1一致
TestController
@RestController
@RequestMapping("/test1")
public class TestController {
@GetMapping("test1")
public Object test(){
return "456789";
}
}
启动两个服务提供者,查看eureka管理页面:
这时候我们发现又出现了一个和zuul网关同一级的一个服务,有些小伙伴会问,我们不是启动了两个服务吗?大家看后边status 列里面是两个服务,因为注册时我们注册的服务名都是 provider1 所以 eurekaserver 将这两个服务解读成一个服务但有两个可用地址.
2.我们再创建第三个服务提供者,并提供一个跟其他两个提供者提供的接口不同的接口,返回值也不同:
创建一个springboot项目,结构如下:
引入 eureka client 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在项目启动类上加上@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient
public class Provider3rdApplication {
public static void main(String[] args) {
SpringApplication.run(Provider3rdApplication.class, args);
}
}
将resources下application.properties文件更名为application.yml:
server:
port: 8083
spring:
application:
name: provider3
eureka:
client:
service-url:
defaultZone: http://localhost:8798/eureka/
instance:
instance_id: ${spring.cloud.client.hostname}:${server.port}
lease-renewal-interval-in-seconds: 5
lease-expiration-duration-in-seconds: 10
在TestController中创建一个对外的接口
@RestController
@RequestMapping("/test3")
public class TestController {
@GetMapping("test3")
public Object test(){
return "789JQK";
}
}
启动第三个服务,查看eureka管理页面:
我们发现多了一个provider3 的服务.
至此,三个服务提供者均已搭建配置完成!
这个时候,我们提到上个问题,网关有什么用呢?
1.zuul可以将我们的服务进行路由
我们访问provider3的test3/test3接口,我们之前是需要访问原始路径:
http://localhost:8083/test3/test3
现在我们有了zuul网关之后,我们可以这样,使用zuul的地址以及privider3的服务名对provider3进行访问:
http://localhost:8086/provider3/test3/test3
这就是一个简单的路由,当然,zuul还可以在yml配置文件中对路由,别名,映射,负载均衡等进行详细配置,具体见demo
2.zuul可以将多个服务提供者的服务整合到一个统一的入口
我们访问provider1的test1/test1接口,我们之前是需要访问原始路径:
http://localhost:8081/test1/test1
我们访问provider2的test1/test1接口,我们之前是需要访问原始路径:
http://localhost:8082/test1/test1
可是我们知道,我们建立provider1和provider2的目的主要是要实验负载均衡的机制,是我们分开访问的话,就不需要负载均衡了,这时候zuul可以这样,上文中使用zuul的地址以及privider1的服务名对provider1进行访问:
http://localhost:8086/provider1/test1/test1
多次访问查看结果,我们发现,返回值在123456和456789之间来回变动,这就是负载均衡的体现.具体的策略有很多种,也可以自定义,自定义的方法我在demo中有写!
4.Feign客户端(feign)
什么是Feign?他是一个Http客户端,可以向指定服务发送http请求,我们什么时候会用到呢,比如一般服务,一个订单的生成,要订单服务请求商品服务获取商品价格,这种情况,客户端请求的是订单服务,但订单服务要请求商品服务获取到商品的价格来生成订单,这时候feign就派上用场了,我们将provider3当做订单服务,provider1当做商品服务,我们修改一下刚刚的provider3的代码,加上feign的支持:
1.在 pom.xml 中加入feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在启动类添加 @EnableFeignClients 注解:
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Provider3rdApplication {
public static void main(String[] args) {
SpringApplication.run(Provider3rdApplication.class, args);
}
}
3.创建一个包 feignClient ,并创建Provider1Client:
@FeignClient(name = "provider1")
public interface Provider1Client {
@GetMapping("test1/test1")
String test1();
}
4.在TestController中添加一个接口 test4:
@RestController
@RequestMapping("/test3")
public class TestController {
@Resource
private Provider1Client provider1Client;
@GetMapping("test3")
public Object test(){
return "789JQK";
}
@GetMapping("test4")
public Object test4(){
String provider1Str = provider1Client.test1();
return "test4" + provider1Str;
}
}
然后重启provider3服务;并访问刚刚添加的test4接口:
http://localhost:8086/provider3/test3/test4
我们发现可以使用feign将privider1以对象的方式将需要暴露给provider3的接口以方法的方式调用,且zuul的负载均衡效果依然生效.文章中只有普通的get请求,且无参数,demo中有详细的说明,get,post patch delete请求,以及参数的各种传输方式的使用.
至此本demo完结,希望能帮助到有需要的小伙伴!
完整demo结构目录如下,项目完整,环境搭建好之后可直接运行:
如有疑问可以随时咨询本人,若各位发现错误请及时提醒,意面误导更多的人,谢谢!
如需下载demo,请移步至:http://www.demodashi.com/demo/16379.html
本文纯手打,谢谢支持!