微服务架构体系讲解(几分钟搞懂微服务)
微服务架构体系讲解(几分钟搞懂微服务)<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.myforever</groupId> <artifactId>zuul-gateway</artifactId> <version>0
现在我们来研究下SpringCloud中Zuul网关的使用,当然之前得说明下为什么要用Zuul网关,毕竟都已经有注册中心中有每个服务的别名了,通过Feign已经完美的调用了,根本不需要Zuul,下面我们就来分析下。
一、为什么要Zuul网关上面随便列举了三个问题,SpringCloud微服务框架中的Zuul技术完美的解决了上面的问题,我们只需要调用同一个ip即可。当然这里需要说明的是,内部服务与服务之间的调用,当然还是通过Feign,虽然说网关也是注册到注册中心的,但是没有必要再加一层,浪费性能。Zuul一般都是用于外部调用我们的微服务。
二、Zuul网关服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
三、实战下面我们实现一个例子,两个服务:127.0.0.1:8001/a 和 127.0.0.1:8002/a我们通过网关直接统一访问127.0.0.1/api-a/a 和127.0.0.1/api-b/b 来访问,并且在网关中做登录验证。
1、环境准备建立三个项目:注册中心、服务a、服务b 然后启动。相信这部通过前面的博文三、服务治理SpringCloud Eureka入门实战下面简单的列一下服务a和b的配置:
服务a###服务提供者启动端口
server:
port: 8001
###服务名称(服务注册到eureka名称)
spring:
application:
name: app-suibibk-zuul-a
###服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
register-with-eureka: true
fetch-registry: true
@RestController
public class AController {
@Value("${server.port}")
private String serverPort;
@RequestMapping("/a")
public String a() {
return "我是a服务" serverPort;
}
}
服务b
###服务提供者启动端口
server:
port: 8002
###服务名称(服务注册到eureka名称)
spring:
application:
name: app-suibibk-zuul-b
###服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
register-with-eureka: true
fetch-registry: true
@RestController
public class BController {
@RequestMapping("/b")
public String a() {
return "我是b服务";
}
}
浏览器下面两个连接保证服务正常http://127.0.0.1:8001/a 返回:我是a服务8001http://127.0.0.1:8002/b 返回:我是b服务
2、建立Zuul网关项目上面服务已经正常启动了,加入我作为一个外部系统,需要访问调用的话,我应该会用http发起http://127.0.0.1:8001/a 和 http://127.0.0.1:8002/b 请求,但是这样的话,需要知道具体的ip,并且比较难做本地的负载均衡(提醒一下:服务之间的调用用Feign默认开启本地负载均衡的),当然Zuul 默认开启了 Ribbon本地负载均衡功能。如果要进行token验证,也就是参数上是否传递token,那么我们可能需要在服务a和服务b中都进行校验。下面用Zuul解决这些问题,项目结构:
其实SpringCloud中建立项目无外乎就是引入依赖,修改配置文件,启动类开启需要的功能什么的。
a、pom.xml<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.myforever</groupId>
<artifactId>zuul-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- SpringBoot整合eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
主要是引入了如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
b、application.yml
###注册 中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
server:
port: 80
###网关名称
spring:
application:
name: app-suibibk-zuul-gateway
zuul:
routes:
#这个名字可以顺便取
api-a:
### 以 /api-a/访问转发到a服务
path: /api-a/**
serviceId: app-suibibk-zuul-a
#这个名字可以顺便取
api-b2:
### 以 /b/访问转发到b服务
path: /api-b/**
serviceId: app-suibibk-zuul-b
这里用80端口,主要是看zuul的配置路由。
/**
* 拦截用户是否有token,没有token就直接报错
* @author forever
*
*/
@Component
public class MyFilter extends ZuulFilter{
@Override
public Object run() throws ZuulException {
//获取上下文
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest reqeust = context.getRequest();
//获取token
String token =reqeust.getParameter("token");
if(token==null) {
context.setSendZuulResponse(false);
context.setResponseStatusCode(403);
context.setResponseBody("token is null");
//return null;
}
System.out.println("执行正常逻辑");
return null;
}
@Override
public boolean shouldFilter() {
// TODO Auto-generated method stub
return true;
}
@Override
public int filterOrder() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String filterType() {
// TODO Auto-generated method stub
return "pre";
}
}
主要关注的是如下几个方法
run()这里做权限验证逻辑,只要能执行完就表示通过。若是不通过则用如下代码来提醒用户
context.setSendZuulResponse(false);
context.setResponseStatusCode(403);
context.setResponseBody("token is null");
shouldFilter()
返回结果表这个过滤器是否生效,true代表生效,false代表不生效。那么什么情况下使用不生效呢,不生效干嘛还要写这个filter类呢?其实是有用的,有时我们会动态的决定让不让一个filter生效,譬如我们可能根据Request里是否携带某个参数来判断是否需要生效,或者我们需要从上一个filter里接收某个数据来决定,再或者我们希望能手工控制是否生效(使用如Appolo之类的配置中心,来动态设置该字段)。
filterOrder()过滤器的执行顺序。当请求在一个阶段的时候存在多个多个过滤器时,需要根据该方法的返回值依次执行。
filterType()主要关注 pre、post和error。分别代表前置过滤,后置过滤和异常过滤。
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class AppZuulGateway {
//默認開啓ribbon负载均衡
public static void main(String[] args) {
SpringApplication.run(AppZuulGateway.class args);
}
}
@EnableZuulProxy表示开启Zuul网关代理功能
3、启动Zuul网关,测试当注册中心Eureka,服务a 服务b Zuul网关都启动后,此时我们可以访问如下链接测试1、http://127.0.0.1/api-a/a 和http://127.0.0.1/api-b/b 返回token is null ,表示Zuul网关拦截请求成功。2、http://127.0.0.1/api-a/a?token=123 返回我是a服务80013、http://127.0.0.1/api-b/b?token=123 返回我是b服务到此,搭建zull网关成功。
四、Nginx与Zuul的区别1、相同点Zuul和Nginx都可以实现负载均衡、反向代理(隐藏真实ip地址),过滤请求,实现网关的效果。
2、不同点Nginx--c语言开发
Zuul--java语言开发
Zuul负载均衡实现:采用ribbon eureka实现本地负载均衡
Nginx负载均衡实现:采用服务器实现负载均衡
Nginx相比zuul功能会更加强大,因为Nginx整合一些脚本语言(Nginx lua)
Nginx适合于服务器端负载均衡
Zuul适合微服务中实现网关
结语
到此,我们就基本上学会了Zuul网关的使用,当然这里只是入门使用,真正想了解深入的话,还需要继续深入研究。暂时来说会用即可,有时间再去深入研究做笔记。