一. 为什么需要网关
在微服务架构设计中,通常会有若干个服务提供者。例如一个券商系统,会有用户系统、开户系统、资讯系统、交易系统等多个服务,而每个服务数量会最着集群部署会变得越来越庞大和复杂。客户端在调用后端系统API时,可能会从多个微服务接口中聚合数据,每个服务又是集群化部署,增加了客户端的复杂性。存在跨域请求的情况,还需要考虑接口鉴权、防火墙/浏览器不友好的协议等影响。网关的作用这时候就显得比较重要。网关对外暴露聚合API,屏蔽内部微服务的变动,保证整个系统的稳定性。它还可以做统一鉴权,监控监测、协议转换等功能。
二. 网关框架都有哪些
目前比较常见的几种开源的网关框架有以下几种:Nginx、Treafik、Kong、Tyk、Ambassador、Zuul 、spring cloud gateway等。至于它们之间的区别,小伙伴自行搜索。如何进行网关选型,也会因业务复杂度、团队使用成本而异。
三. 博客提纲
本博客介绍如何使用Zuul构建一个简单的网关、介绍路由配置方式。要点内容如下:
客户端通过zuul网关调用微服务接口的的关系图:
1.zuul的相关概念
Zuul是Netflix开源的微服务网关[1],他可以和Eureka,Ribbon,Hystrix等组件配合使用。Zuul组件的核心是一系列的过滤器,这些过滤器可以完成以下功能:
1) 身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求;
2) 审查与监控;
3) 动态路由:动态将请求路由到不同后端集群;
4) 压力测试:逐渐增加指向集群的流量,以了解性能;
5) 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求;
6) 静态响应处理:边缘位置进行响应,避免转发到内部集群;
7) 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化。
2.zuul的依赖和配置
1)依赖库
def alibabaCloudVersion = '2.2.3.RELEASE'def spring_boot_version = "2.3.2.RELEASE"
ext {set('springCloudVersion', "Hoxton.SR8")}
在dependencies 中添加:// nacosimplementation "com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:${alibabaCloudVersion}"// zuulimplementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul'
2)application配置
@SpringBootApplication@EnableDiscoveryClient // 允许注册nacos@EnableZuulProxy // 开启 zuul代理public class ZuulApplication {public static void main(String[] args) {SpringApplication.run(ZuulApplication.class, args);}}
3)bootstrap.yml配置文件
server:port: 8852spring:application:name: zuul_gatewaymain:allow-bean-definition-overriding: truecloud:nacos: discovery: # 注册到nacosserver-addr: localhost:8848
启动nacos(如何安装和启动nacos,请看我的博客《如何在Mac下安装nacos》),运行ZuulApplication,在浏览器输入:http://localhost:8848/nacos/#/login, 输入账号和密码:nacos、nacos,我们看到 zuul已经被注册到nacos了。
3.实现服务提供者
在本博客中,博主定义了crm, user两个微服务提供者,分别对外暴露两个接口。
1) cms提供者的主要实现
@Servicepublic class CmsServcie {public String getContent() {return "Contentn from cms";}public String saveContent() {return "Save content to cms";}}
@RestControllerpublic class CmsController {public static final String CMS_GET_CONTENT = "cms/getContent";public static final String CMS_SAVE_CONTENT = "cms/saveContent";@Autowiredprivate CmsServcie servcie;@GetMapping(path = CMS_GET_CONTENT)@LoadBalancedpublic String getContent() {return servcie.getContent();}@GetMapping(path = CMS_SAVE_CONTENT)@LoadBalancedpublic String saveContent() {return servcie.saveContent();}}
@SpringBootApplication@EnableDiscoveryClientpublic class CmsApplication {public static void main(String[] args) {SpringApplication.run(CmsApplication.class, args);}}
bootstrap.yml配置:
server:port: 8851spring:application:name: cmscloud:nacos:discovery:server-addr: localhost:8848profiles:active: devribbon:#http请求连接建立超时时间(ms)ConnectTimeout: 10000#http请求处理超时时间(ms)ReadTimeout: 15000#默认重试次数MaxAutoRetries: 1#默认尝试的实例数MaxAutoRetriesNextServer: 4
gradle依赖同zuul。
运行CmsApplication,cms被注册到 nacos。
2) user提供者的主要实现
@Servicepublic class UserService {public String login() {return "Login successful";}public String logout() {return "Logout successful";}}
@RestControllerpublic class UserController {public static final String USER_LOGIN = "user/login";public static final String USER_LOGOUT = "user/logout";@Autowiredprivate UserService service;@GetMapping(path = USER_LOGIN)@LoadBalancedpublic String login() {return service.login();}@GetMapping(path = USER_LOGOUT)@LoadBalancedpublic String getUserLogout() {return service.logout();}}
@SpringBootApplication@EnableDiscoveryClientpublic class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}}
bootstrap.yml配置:
server:port: 8850spring:application:name: usercloud:nacos:config:server-addr: localhost:8848file-extension: yamlprefix: userdiscovery:server-addr: localhost:8848profiles:active: devribbon:#http请求连接建立超时时间(ms)ConnectTimeout: 10000#http请求处理超时时间(ms)ReadTimeout: 15000#默认重试次数MaxAutoRetries: 1#默认尝试的实例数MaxAutoRetriesNextServer: 4
gradle依赖同zuul。
运行UserApplication,user被注册到 nacos。
4.zuul调用cms、user的接口实现
1)静态路由设置
在zuul的bootstrap.yml中添加以下路由配置:
zuul:routes:# cms路由cms: # 微服务的serverIDserviceId: cmspath: /cms/**stripPrefix: false # 设置为false,表示不增加前缀# user路由user: # 微服务的serverIDserviceId: userpath: /user/**stripPrefix: false # 设置为false,表示不增加前缀
路由说明:
服务提供者的接口被映射成 :http://localhost:8852/serverID/路径,http://localhost:8852是zuul的host和端口。
例如调用user 的login接口,原API是http://localhost:8850/user/logout,被zuul路由映射成API:http://localhost:8852/user/logout。
2)重新运行ZuulApplication。调用在浏览器输入:http://localhost:8852/user/logout,我们看到zuul已经成功调用user的logout接口。同理,user的login接口、cms的其他两个接口也可以这么访问。
四. 总结
通过就是在nacos注册中心中简单实现zuul网关的全部内容。博客的demo代码可以github上下载。感谢您的阅读。