概述
Zuul:
Spring Cloud使用Zuul来作为路由网关,网关的功能对于分布式网站十分重要。Zuul主要有三个功能:
- 路由:将请求路由到真实额服务器上,进而保护真实服务器的IP地址,避免直接地攻击真实服务器。
- 负载均衡:将请求按照一点的算法分摊到多个微服务节点上,减缓单点的压力。
- 过滤器:判断请求是否为有效请求,一旦判定失败,就可以将请求阻止,避免发送到真实的服务器,这样就能降低真实服务器的压力。
开发环境:
- 开发工具:IntelliJ IDEA
- Java版本:1.8
- Spring Boot版本:2.1.6.RELEASE
- Spring Cloud版本:Greenwich.SR1
1、创建server-eureka微服务:
(1)server-eureka组件选择
(2)server-eureka目录
(3)application.yml
server:
#服务端口
port: 9000
spring:
application:
#服务名称
name: server
eureka:
#配置环境
environment: dev
#配置数据中心
datacenter: nanjing
instance:
#注册服务器名称
hostname: localhost
client:
#是否注册到服务中心
register-with-eureka: false
#是否检索服务
fetch-registry: false
service-url:
#客户端服务域
defaultZone: http://localhost:9000/eureka/
(4)ServerEurekaApplication
package com.ming.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //开启Eureka服务端
public class ServerEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(ServerEurekaApplication.class, args);
}
}
2、创建client-user微服务:
(1)client-user组件选择
(2)client-user目录
(3)application.yml
#配置第一个用户微服务
server:
#服务端口
port: 7001
spring:
#区分不同环境下的配置文件(启动工程时使用)
profiles: user1
#服务名称
application:
name: user
eureka:
client:
service-url:
#服务注册地址
defaultZone: http://localhost:9000/eureka/
#隔离线
---
#配置第二个用户微服务
server:
#服务端口
port: 7002
spring:
#区分不同环境下的配置文件(启动工程时使用)
profiles: user2
#服务名称
application:
name: user
eureka:
client:
service-url:
#服务注册地址
defaultZone: http://localhost:9000/eureka/
(4)ClientUserApplication
package com.ming.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //开启Eureka客户端
public class ClientUserApplication {
public static void main(String[] args) {
SpringApplication.run(ClientUserApplication.class, args);
}
}
(5)UserController
package com.ming.user.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@RequestMapping("/timeout")
public String timeout() {
//调用服务时间
Timestamp time = new Timestamp(System.currentTimeMillis());
//生成一个2000之内的随机数
long ms = (long) (2000 * Math.random());
System.out.println("服务耗时:" + ms + " ms");
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("调用服务时间:" + time + ",服务耗时:" + ms + " ms");
return "调用服务时间:" + time + " -> 未超时,服务正常";
}
}
3、创建client-zuul微服务:
(1)client-zuul组件选择
(2)client-zuul目录
(3)application.yml
server:
#服务端口,浏览器默认端口,地址栏可不用显示输入该端口号
port: 80
spring:
#服务名称
application:
name: zuul
eureka:
client:
service-url:
#服务注册地址
defaultZone: http://localhost:9000/eureka/
(4)ClientZuulApplication
package com.ming.zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy //开启zuul网关(默认引入断路机制)
public class ClientZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ClientZuulApplication.class, args);
}
}
4、工程测试:
(1)配置client-user运行环境
client-user微服务要启动两个实例,来测试Zuul的负载均衡功能,配置运行环境如下:
(2)微服务运行目录
(3)测试原始路由功能
依次点击ServerEurekaApplication、ClientUserApplication1、ClientUserApplication2、ClientZuulApplication,工程都启动成功后。在浏览器地址栏访问 http://localhost:9000,其结果如下(四个微服务实例启动正常):
在浏览器地址栏访问 http://localhost/user/timeout, 其结果如下:
在 http://localhost/user/timeout 中,localhost代表的是请求Zuul服务,因为采用的是默认的80端口,所以浏览器地址可以不给出端口号,user代表的是client-user微服务的serviceId (application.yml中的spring.application.name属性值),而timeout是请求路径,这样就会将请求转发到client-user微服务。
(4)测试负载均衡功能
改写client-zuul微服务配置文件application.yml:
server:
#服务端口,浏览器默认端口,地址栏可不用显示输入
port: 80
spring:
#服务名称
application:
name: zuul
zuul:
routes:
user-service:
#配置client-user微服务请求路径
path: /u/**
#指定转发地址,zuul将请求转发到client-user微服务上,由于给定了服务端口号,无法实现负载均衡
#url: http://localhost:7001/
#指定服务ID,zuul将请求转发到client-user微服务上,自动使用服务端负载均衡,分摊请求
serviceId: user
eureka:
client:
service-url:
#服务注册地址
defaultZone: http://localhost:9000/eureka/
在service包下创建ZuulFallBackService类,实现降级服务,Zuul默认启用断路机制:
package com.ming.zuul.service;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@Service
public class ZuulFallBackService implements FallbackProvider {
@Override
public String getRoute() {
//client-user微服务serviceId(spring.application.name)
return "user";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpHeaders getHeaders() {
//设置请求头
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
return httpHeaders;
}
@Override
public InputStream getBody() {
//设置请求体
return new ByteArrayInputStream("超时,服务异常".getBytes());
}
@Override
public HttpStatus getStatusCode() {
//设置响应状态
return HttpStatus.REQUEST_TIMEOUT;
}
@Override
public int getRawStatusCode() {
//设置响应状态码
return HttpStatus.REQUEST_TIMEOUT.value();
}
@Override
public String getStatusText() {
//设置响应状态信息
return HttpStatus.REQUEST_TIMEOUT.getReasonPhrase();
}
@Override
public void close() {
}
};
}
}
依次点击ServerEurekaApplication、ClientUserApplication1、ClientUserApplication2、ClientZuulApplication,工程都启动成功后。在浏览器地址栏访问 http://localhost:9000,其结果如下(四个微服务实例启动正常):
在浏览器地址栏访问 http://u/timeout, 其结果如下:
然后查看控制台ClientUserApplication1,结果如下:
默认响应时长超过1000ms,启用熔断机制,进行降级服务。然而每个请求默认有1次重试机会,查看控制台ClientUserApplication2,如下:
第二次重新请求,响应未超时,微服务被正常调用。从上面图中可以看到,两次请求的client-zuul服务端口号分别为7002、7001,Zuul默认采用轮询机制实现负载均衡。
再次在浏览器地址栏访问 http://u/timeout, 其结果如下:
查看控制台ClientUserApplication1、ClientUserApplication2,结果如下:
两次请求均超时,启用熔断机制,进行降级服务。
(5)测试过滤器功能
访问 http://localhost/u/timeout?serialId=521&authCode=123, 当serialId与authCode一致时,Zuul转发请求到client-user微服务;访问 http://localhost/u/timeout?serialId=521&authCode=521, 当serialId与authCode不一致时,不再转发到微服务,浏览器页面显示 " 服务认证失败!"。
在service包下创建ZuulFilterService类:
package com.ming.zuul.service;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
@Service
public class ZuulFilterService extends ZuulFilter {
@Override
public String filterType() {
//设置前置过滤
return "pre";
}
@Override
public int filterOrder() {
//设置过滤器顺序,数字越小,优先级越高
return 0;
}
@Override
public boolean shouldFilter() {
//获取当前请求上下文
RequestContext currentContext = RequestContext.getCurrentContext();
//获取HttpServletRequest对象
HttpServletRequest request = currentContext.getRequest();
//获取请求参数序列Id
String serialId = request.getParameter("serialId");
//如果存在序列Id,则启用过滤器
return !StringUtils.isEmpty(serialId);
}
@Override
public Object run() {
//获取当前请求上下文
RequestContext currentContext = RequestContext.getCurrentContext();
//获取HttpServletRequest对象
HttpServletRequest request = currentContext.getRequest();
//获取请求参数序列Id
String serialId = request.getParameter("serialId");
//获取请求参数认证码
String authCode = request.getParameter("authCode");
if (!serialId.equals(authCode)) {
//设置不在转发请求
currentContext.setSendZuulResponse(false);
//设置HTTP状态响应码
currentContext.setResponseStatusCode(401);
//设置响应编码,防止出现响应页面乱码
currentContext.getResponse().setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//设置响应体
currentContext.setResponseBody("服务认证失败!");
}
return null;
}
}
依次点击ServerEurekaApplication、ClientUserApplication1、ClientUserApplication2、ClientZuulApplication,工程都启动成功后。在浏览器地址栏访问 http://localhost:9000,其结果如下(四个微服务实例启动正常):
在浏览器地址栏访问 http://localhost/u/timeout?serialId=521&authCode=123, 其结果如下:
在浏览器地址栏访问 http://localhost/u/timeout?serialId=521&authCode=521, 其结果如下:
最后
以上就是无辜电话为你收集整理的SpringCloud2组件之Zuul详解的全部内容,希望文章能够帮你解决SpringCloud2组件之Zuul详解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复