随着互联网的快速发展,当前以步入移动互联、物联网时代。用户访问系统入口也变得多种方式,由原来单一的PC客户端,变化到PC客户端、各种浏览器、手机移动端及智能终端等。同时系统之间大部分都不是单独运行,经常会涉及与其他系统对接、共享数据的需求。所以系统需要升级框架满足日新月异需求变化,支持业务发展,并将框架升级为微服务架构。“API网关”核心组件是架构用于满足此些需求。
很多互联网平台已基于网关的设计思路,构建自身平台的API网关,国内主要有京东、携程、唯品会等,国外主要有Netflix、Amazon等。
业界为了满足这些需求,已有相关的网关框架。
1、基于nginx平台实现的网关有:KONG、API Umbrella
2、自研发的网关有:apigee、Zuul
API网关是微服务架构(Microservices Architecture)标准化服务的模式。API网关定位为应用系统服务接口的网关,区别于网络技术的网关,但是原理则是一样。API网关统一服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证、防报文重放与防数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等。组件设计如下:
API网关是一个公共基础组件,无状态,可支持多套分布式部署。如下图所示:
Nginx配置
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location /api-a { proxy_pass http://127.0.0.1:8000/; index index.html index.htm; } location /api-b { proxy_pass http://127.0.0.1:8001/; index index.html index.htm; } } } |
eureka_server pom依赖信息
<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.0modelVersion> <groupId>com.itmayiedugroupId> <artifactId>eureka_serverartifactId> <version>0.0.1-SNAPSHOTversion> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>2.0.1.RELEASEversion> parent>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-dependenciesartifactId> <version>Finchley.M7version> <type>pomtype> <scope>importscope> dependency> dependencies> dependencyManagement> <dependencies>
<dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId> dependency>
dependencies>
<repositories> <repository> <id>spring-milestonesid> <name>Spring Milestonesname> <url>https://repo.spring.io/libs-milestoneurl> <snapshots> <enabled>falseenabled> snapshots> repository> repositories>
<build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> plugin> plugins> build> project> |
application.yml 配置信息
server: port: 8100 eureka: instance: hostname: server1 client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ register-with-eureka: false fetch-registry: false |
server: port: 8100 eureka: instance: hostname: server1 client: serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ register-with-eureka: false fetch-registry: false |
启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(final String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class AIndexController {
@RequestMapping("/")
public String index() {
return "我是A项目....";
}
public static void main(String[] args) {
SpringApplication.run(AIndexController.class, args);
}
}
server: port: 8000 spring: application: name: itmayiedu_a eureka: client: service-url: defaultZone: http://localhost:8100/eureka |
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class AIndexController {
@RequestMapping("/")
public String index() {
return "我是B项目....";
}
public static void main(String[] args) {
SpringApplication.run(AIndexController.class, args);
}
}
server: port: 8000 spring: application: name: itmayiedu_a eureka: client: service-url: defaultZone: http://localhost:8100/eureka |
创建 zuul-gateway Pom依赖
<parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>2.0.1.RELEASEversion> <relativePath /> parent>
<properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding> <java.version>1.8java.version> <spring-cloud.version>Finchley.RC1spring-cloud.version> properties> <dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starterartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-ribbonartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-netflix-zuulartifactId> dependency> <dependency> <groupId>org.projectlombokgroupId> <artifactId>lombokartifactId> <optional>trueoptional> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>fastjsonartifactId> <version>1.2.3version> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> dependency> dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-dependenciesartifactId> <version>${spring-cloud.version}version> <type>pomtype> <scope>importscope> dependency> dependencies> dependencyManagement>
<build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> plugin> <plugin> <groupId>org.apache.maven.pluginsgroupId> <artifactId>maven-compiler-pluginartifactId> <configuration> <source>1.8source> <target>1.8target> configuration> plugin> <plugin> <groupId>org.apache.maven.pluginsgroupId> <artifactId>maven-resources-pluginartifactId> <version>3.0.1version> <executions> <execution> <id>copy-confid> <phase>packagephase> <goals> <goal>copy-resourcesgoal> goals> <configuration> <encoding>UTF-8encoding> <outputDirectory>${project.build.directory}/ext/confoutputDirectory> <resources> <resource> <directory>ext/confdirectory> <includes> <include>logback.xmlinclude> includes> <filtering>truefiltering> resource> resources> configuration> execution> executions> plugin> <plugin> <groupId>org.jacocogroupId> <artifactId>jacoco-maven-pluginartifactId> <version>0.7.5.201505241946version> <executions> <execution> <id>default-prepare-agentid> <goals> <goal>prepare-agentgoal> goals> execution> <execution> <id>default-prepare-agent-integrationid> <goals> <goal>prepare-agent-integrationgoal> goals> execution> executions> plugin> <plugin> <groupId>com.spotifygroupId> <artifactId>docker-maven-pluginartifactId> <version>0.4.3version> <configuration> <imageName>hy_uav_gatewayimageName> <dockerDirectory>src/main/dockerdockerDirectory> <resources> <resource> <targetPath>/targetPath> <directory>${project.build.directory}directory> <include>${project.build.finalName}.jarinclude> <include>ext/conf/logback.xmlinclude> resource> resources> configuration> plugin> plugins> build>
<repositories> <repository> <id>spring-milestonesid> <name>Spring Milestonesname> <url>https://repo.spring.io/milestoneurl> <snapshots> <enabled>falseenabled> snapshots> repository> repositories> |
配置application 依赖信息
eureka: client: serviceUrl: defaultZone: http://localhost:8100/eureka/ server: port: 8769 spring: application: name: service-zuul zuul: routes: api-a: path: /api-a/** serviceId: itmayiedu_a api-b: path: /api-b/** serviceId: itmayiedu_b |
ZuulApplication启动运行
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
@Bean
public TokenFilter accessFilter() {
return new TokenFilter();
}
}
过滤器拦截参数
// 使用网关拦截Token参数
public class TokenFilter extends ZuulFilter {
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
Object accessToken = request.getParameter("accessToken");
if (accessToken == null) {
// 返回错误信息
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.setResponseBody("accessToken is null");
return null;
}
return null;
}
public boolean shouldFilter() {
return true;// 是否执行该过滤器,此处为true,说明需要过滤
}
@Override
public int filterOrder() {
return 0;// 优先级为0,数字越大,优先级越低
}
@Override
public String filterType() {
return "pre"; // 前置过滤器
}
}