微服务架构: 基于nacos注册中心的Zuul网关实现

一. 为什么需要网关

在微服务架构设计中,通常会有若干个服务提供者。例如一个券商系统,会有用户系统、开户系统、资讯系统、交易系统等多个服务,而每个服务数量会最着集群部署会变得越来越庞大和复杂。客户端在调用后端系统API时,可能会从多个微服务接口中聚合数据,每个服务又是集群化部署,增加了客户端的复杂性。存在跨域请求的情况,还需要考虑接口鉴权、防火墙/浏览器不友好的协议等影响。网关的作用这时候就显得比较重要。网关对外暴露聚合API,屏蔽内部微服务的变动,保证整个系统的稳定性。它还可以做统一鉴权,监控监测、协议转换等功能。

二. 网关框架都有哪些

目前比较常见的几种开源的网关框架有以下几种:Nginx、Treafik、Kong、Tyk、Ambassador、Zuul 、spring cloud gateway等。至于它们之间的区别,小伙伴自行搜索。如何进行网关选型,也会因业务复杂度、团队使用成本而异。

三. 博客提纲

本博客介绍如何使用Zuul构建一个简单的网关、介绍路由配置方式。要点内容如下:

微服务架构: 基于nacos注册中心的Zuul网关实现_第1张图片

客户端通过zuul网关调用微服务接口的的关系图:

微服务架构: 基于nacos注册中心的Zuul网关实现_第2张图片

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 中添加:
   // nacos
   implementation "com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:${alibabaCloudVersion}"
   // zuul
   implementation '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: 8852
spring:
  application:
    name: zuul_gateway
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos: 
      discovery: # 注册到nacos
        server-addr: localhost:8848

启动nacos(如何安装和启动nacos,请看我的博客《如何在Mac下安装nacos》),运行 ZuulApplication,在浏览器输入:http://localhost:8848/nacos/#/login, 输入账号和密码:nacos、nacos,我们看到 zuul已经被注册到nacos了。

微服务架构: 基于nacos注册中心的Zuul网关实现_第3张图片

3.实现服务提供者

在本博客中,博主定义了crm, user两个微服务提供者,分别对外暴露两个接口。

1) cms提供者的主要实现

@Service
public class CmsServcie {
    public String getContent() {
        return "Contentn from cms";
    }

    public String saveContent() {
        return "Save content to cms";
    }
}
@RestController
public class CmsController {
    public static final String CMS_GET_CONTENT = "cms/getContent";
    public static final String CMS_SAVE_CONTENT = "cms/saveContent";

    @Autowired
    private CmsServcie servcie;

    @GetMapping(path = CMS_GET_CONTENT)
    @LoadBalanced
    public String getContent() {
        return servcie.getContent();
    }

    @GetMapping(path = CMS_SAVE_CONTENT)
    @LoadBalanced
    public String saveContent() {
        return servcie.saveContent();
    }
}
@SpringBootApplication
@EnableDiscoveryClient
public class CmsApplication {
   public static void main(String[] args) {
      SpringApplication.run(CmsApplication.class, args);
   }

}

bootstrap.yml配置:

server:
  port: 8851
spring:
  application:
    name: cms
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

  profiles:
    active: dev

ribbon:
  #http请求连接建立超时时间(ms)
  ConnectTimeout: 10000
  #http请求处理超时时间(ms)
  ReadTimeout: 15000
  #默认重试次数
  MaxAutoRetries: 1
  #默认尝试的实例数
  MaxAutoRetriesNextServer: 4

gradle依赖同zuul。

运行CmsApplication,cms被注册到 nacos。

2) user提供者的主要实现

@Service
public class UserService {
    public String login() {
        return "Login successful";
    }

    public String logout() {
        return "Logout successful";
    }
}
@RestController
public class UserController {
    public static final String USER_LOGIN = "user/login";
    public static final String USER_LOGOUT = "user/logout";

    @Autowired
    private UserService service;

    @GetMapping(path = USER_LOGIN)
    @LoadBalanced
    public String login() {
        return service.login();
    }

    @GetMapping(path = USER_LOGOUT)
    @LoadBalanced
    public String getUserLogout() {
        return service.logout();
    }
}
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {

   public static void main(String[] args) {
      SpringApplication.run(UserApplication.class, args);
   }

}

bootstrap.yml配置:

server:
  port: 8850
spring:
  application:
    name: user
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        file-extension: yaml
        prefix: user
      discovery:
        server-addr: localhost:8848

  profiles:
    active: dev

ribbon:
  #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: #  微服务的serverID
      serviceId: cms
      path: /cms/**
      stripPrefix: false # 设置为false,表示不增加前缀
    # user路由
    user: # 微服务的serverID
      serviceId: user
      path: /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网关实现_第4张图片

四. 总结

通过就是在nacos注册中心中简单实现zuul网关的全部内容。博客的demo代码可以github上下载。感谢您的阅读。
 

 

你可能感兴趣的:(后端,java,spring,spring,boot,后端)