一、API网关简介
在微服务架构中,通常会有多个服务提供者。设想一个电商系统,可能会有商品、订单、支付、用户等多个类型的服务,而每个类型的服务数量也会随着整个系统体量的增大也会随之增长和变更。作为UI端,在展示页面时可能需要从多个微服务中聚合数据,而且服务的划分位置结构可能会有所改变。网关就可以对外暴露聚合API,屏蔽内部微服务的微小变动,保持整个系统的稳定性。
当然这只是网关众多功能中的一部分,它还可以做负载均衡,统一鉴权,协议转换,监控监测等一系列功能。
二、Zuul简介
Zuul是Spring Cloud全家桶中的微服务API网关。
所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序。作为一个边界性质的应用程序,Zuul提供了动态路由、监控、弹性负载和安全功能。Zuul底层利用各种filter实现如下功能:
认证和安全 识别每个需要认证的资源,拒绝不符合要求的请求。
性能监测 在服务边界追踪并统计数据,提供精确的生产视图。
动态路由 根据需要将请求动态路由到后端集群。
压力测试 逐渐增加对集群的流量以了解其性能。
负载卸载 预先为每种类型的请求分配容量,当请求超过容量时自动丢弃。
静态资源处理 直接在边界返回某些响应。
Zuul包含了对请求的路由和过滤两个最主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得.
注意:Zuul服务最终还是会注册进Eureka
提供=代理+路由+过滤三大功能
三、Eureka简介
1、Spring-Cloud Euraka介绍
Spring-Cloud Euraka是Spring Cloud集合中一个组件,它是对Euraka的集成,用于服务注册和发现。Eureka是Netflix中的一个开源框架。它和 zookeeper、Consul一样,都是用于服务注册管理的,同样,Spring-Cloud 还集成了Zookeeper和Consul。
在项目中使用Spring Cloud Euraka的原因是它可以利用Spring Cloud Netfilix中其他的组件,如zull等,因为Euraka是属于Netfilix的。
2、Euraka介绍
Eureka由多个instance(服务实例)组成,这些服务实例可以分为两种:Eureka Server和Eureka Client。为了便于理解,我们将Eureka client再分为Service Provider和Service Consumer。
(1)Eureka Server 提供服务注册和发现
(2)Service Provider 服务提供方,将自身服务注册到Eureka,从而使服务消费方能够找到
(3)Service Consumer服务消费方,从Eureka获取注册服务列表,从而能够消费服务
3.cap原理(CAP三个属性对于分布式系统不能同时做到)
P:Partition tolerance,网络分区容错。类似多机房部署,保证服务稳定性。
A: Availability,可用性。
C:Consistency ,一致性。
Eureka是AP,高可用与可伸缩的Service发现服务,突出可用性。
四、集成Eureka和Zuul(使用idea)
为了减少占用内存,建议创建maven工程
1.集成 Eureka Server
(1)新建Module,选择 spring initializr, 选择如下依赖,如果未选择,不要担心,在pom.xml文件中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(2)在application.properties文件中添加
#当前服务名
spring.application.name=eureka
#端口号
server.port=8761
# #Eureka是为注册中心,是否需要将自己注册到注册中心上(默认为true),
# 本次位单机部署,不需要设置为true;但是注册中心集群时候必须为true;因为集群时,其 他Eureka需要从此Eureka中的节点上获取数据;
eureka.client.register-with-eureka=false
#Erueka是为注册中心,不需要检索服务信息;
# (表示是否从Eureka Server获取注册信息,默认为true。 如果这是一个单点的 Eureka Server,不需要同步其他节点的数据,可以设为false)
eureka.client.fetch-registry=false
#覆盖默认地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
(3)在启动类上添加 @EnableEurekaServer
(4)浏览器输入 localhost:8761
2.集成 Service Consumer
(1)新建Module,选择 spring initializr, 选择如下依赖,如果未选择,不要担心,在pom.xml文件中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)在application.properties文件中添加
spring.application.name=consumer
server.port=8762
eureka.client.service-url.defaultZone=http://localhost:8761/eureka #Eureka Server 的端口号
(3)启动类
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
}
(4)controller
@RestController
public class TestController {
@Autowired
@Qualifier("restTemplate")
RestTemplate restTemplate;
/**
* 处理get请求
* @return
*/
@GetMapping("/hello")
public String hello(){
return restTemplate.getForObject("http://localhost:8763/hello",String.class);
}
}
(4)浏览器输入 localhost:8761,新增内容如下
3.集成Service Provider,创建方式同 Service Consumer
(1)在application.properties文件中添加
spring.application.name=provider
server.port=8763
eureka.client.service-url.defaultZone=http://localhost:8761/eureka #Eureka Server 的端口号
(2)controller
@RestController
public class TestController {
@Value("${server.port}")
Integer port;
@GetMapping("/hello") #路径名称
public String hello(){
return "hello "+port;
}
}
(3)浏览器输入 localhost:8761,新增内容如下
4. zuul集成
(1)创建同上,多加一个依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)在application.properties文件中添加
spring.application.name=zuul
server.port=8764
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
#匹配规则(最好设计阶段就避免) 将properties改为yml
zuul.routes.consumer=/test/**
#zuul.routes.consumer-hello=/consumer/hello/**
#忽略服务
#zuul.ignored-services=provider
#忽略请求
#zuul.ignored-patterns=/**/hello/**
#前缀
#zuul.prefix=/javaboy
(3)新建类(一定要加@Component)
@Component
public class PermissFilter extends ZuulFilter {
/**
* 过滤器类型,一般是pre
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤优先级
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否过滤
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 处理过滤逻辑
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest req = ctx.getRequest();
String token = req.getParameter("myToken"); //
if(!"123".equals(token)){
ctx .setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
ctx.setResponseBody("非法访问");
}
return null;
}
}
(4)在启动类上加@EnableZuulProxy
(5)浏览器输入 localhost:8761,新增内容如下
(6)测试
浏览器输入 localhost:8764/test/hello
浏览器输入 localhost:8764/test/hello?myToken=123