微服务网关

API(接口)  Gateway(网关)

接口分类:

  外部接口:

    其他机构合作伙伴进行调用(必须在外网访问),蚂蚁开放平台,微信公众号开发 需要通过appid + appsocet生成accessToken进行通讯。

  内部接口:

    一般只能在局域网中进行访问,服务与服务调用之间都在同一个微服务系统中。目 的是为了保证安全

 

如何设计一套api接口:

  • 接口权限(开放接口 | 内部接口)
  • 考虑幂等性
  • 安全性(Https
  • 防止篡改数据(验证签名)
  • 使用网关拦截接口实现接口的黑名单和白名单
  • 接口使用Http + json格式,目的是为了跨平台
  • 考虑高并发,实现服务保护(降级,隔离,熔断)
  • 最后使用统一的API管理平台api swagger

网关

网关分为内网网关和外网网关,相当于客户端请求统一请求到网关服务器上,再由网关服务器进行转发到实际的服务地址上,类似于Nginx

网关的作用:网关可以拦截客户端所有请求,对该请求进行权限控制,负载均衡,日志管理,接口调用监控等

过滤器与网关的区别:过滤器适合单个tomcat服务器进行拦截请求。网关是拦截整个微服务的所有请求

Zuul

Nginx与Zuul的区别

相同点:都可以实现负载均衡,反向代理,过滤请求,实现网关效果

不同点Nginx采用c语言编写,Zuul采用java语言编写;Zuul实现负载均衡采用ribbon+eureka实现本地负载均衡,Nginx实现负载均衡采用服务器实现负载均衡;NginxZuul功能会更加强大,因为Nginx能整合一些脚本语言(Nginx+Lua);Nginx适合于服务端负载均衡,Zuul适合微服务中的网关

最好是Nginx+Zuul实现网关Nginx实现反向代理,Zuul对微服务实现网关拦截

搭建Zuul网关系统

Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<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>com.jx.zuul</groupId>
    <artifactId>zuul_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <!-- web starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- zuul依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <!-- eureka客户端依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
View Code

application.yml配置

# 服务注册地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8100/eureka
# 网关端口
server:
  port: 80
# 网关名称
spring:
  application:
    name: server-zuul

zuul:
  routes:
    api-a:   # api-a这个是随便写的,也可以写api-member
      # 当客户端发送请求127.0.0.1:80/api-member/**时,都会转发到serviceId为jx-member的服务
      path: /api-member/**
      # 服务别名,zuul网关默认整合ribbon,自动实现负载均衡
      serviceId: jx-member
    api-b:
      path: /api-order/**
      serviceId: jx-order

在启动类上标注@EnableZuulProxy开启网关代理

@SpringBootApplication
@EnableZuulProxy   // 开启网关代理
@EnableEurekaClient
public class ZuulDemoApplication {

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

然后通过127.0.0.1:80/api-member/ 就可以访问到会员服务的地址了

搭建ZuulFilter拦截请求参数

搭建ZuulFilter拦截请求非常简单,只需要写一个类继承ZuulFilter类即可,然后将这个类添加到容器即可

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class TokenFilter extends ZuulFilter {
    /**
     * 过滤器类型
     * return "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 currentContext = RequestContext.getCurrentContext();
        // 获取request
        HttpServletRequest request = currentContext.getRequest();
        // 获取Token,从请求头获取
        String userToken = request.getParameter("userToken");
        if (StringUtils.isEmpty(userToken)) {
            // 不会继续执行,不会调用服务接口,网关服务直接响应客户端
            currentContext.setSendZuulResponse(false);    // 封装到map中
            currentContext.setResponseBody("userToken is empty!");  // 封装到map中
            currentContext.setResponseStatusCode(401);
            return null;
        }
        // 正常调用其他服务
        return null;
    }
}

搭建动态Zuul网关路由转发

需求,如果在服务器启动的时候,我们需要给网关添加路由规则,比如加个api-c,这时候是需要重启服务器的,但是如果我们结合SpringCloud Config分布式配置中心,就能实现动态路由规则

导入Maven依赖

这里导入的是config-client依赖,假设configServer已经搭建好了

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>

然后将zuul相关配置写到gitee上面

命名为zuul-server-dev.yml

然后在本地配置bootstrap.yml

# 服务注册地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8100/eureka
# 网关端口
server:
  port: 80
# 网关名称
spring:
  application:
    name: zuul-server
  cloud:
    config:
      # 读取的环境
      profile: dev
      discovery:
        # ConfigServer在注册中心上的名字
        service-id: config-server
        # 开启读取权限
        enabled: true

最后在启动类上添加zuulProperties()使zuul能够使用config

public class ZuulDemoApplication {

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

    // zuul配置能够使用config实现实时更新
    @RefreshScope
    @ConfigurationProperties("zuul")
    public ZuulProperties zuulProperties() {
        return new ZuulProperties();
    }
}

之后访问127.0.0.1:80/api-member/** 即可转发到会员服务

实现网关集群

Zuul如何实现搭建集群版本: Nginx +Zuul一主一备或者轮询多个

上图即是zuul搭建集群的基本思想:

客户端发送请求统一到Nginx上,在使用Nginx实现反向代理和负载均衡,然后采用轮询算法转发到网关上,最后由网关转发请求到对应的服务

posted @ 2018-12-09 17:44  Jin同学  阅读(295)  评论(0)    收藏  举报