zoukankan      html  css  js  c++  java
  • 升级微服务架构5:API网关

      API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
      按照使用场景来说,API网关只要用来给外部应用(PC客户端、移动端,外部系统等)提供API接口。上一章已经实现了系统内部服务的相互调用,内部服务是不对外开放的,外部应用要调用服务,则需要API网关来实现路由。
      Spring Cloud整合的API网关有:Netflix的zuul以及自研的Spring Cloud Gateway,目前使用zuul的比较多,资料也比较全,这里采用zuul作为API网关。

      1.创建API网关服务

      1.1添加zuul依赖

      创建一个空的Maven项目apigateway,并添加zuul的依赖,因为API网关也是一个服务,需要注册到Eureka Server,所以还需要添加Eureka Client的依赖。  

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>

      在启动类上添加@EnableZuulProxy注解

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    
    @SpringBootApplication
    @EnableEurekaClient
    @EnableZuulProxy
    public class ApiGatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(ApiGatewayApplication.class, args);
        }
    }

      配置文件设置好端口及服务中心地址

    server:
      port: 5551 #服务端口
    
    eureka:
      client:
        registerWithEureka: true #是否注册
        fetchRegistry: true #启用客户端缓存
        serviceUrl:
          defaultZone: http://peer1:8881/eureka/,http://peer2:8882/eureka/ #注册到两个服务中心
    
    spring:
      application:
        name: apigateway #服务名

      依次启动Eureka Server、订单服务、用户服务、API网关服务,浏览器带Eureka Server页面,发现API网关服务已注册成功。

      

      1.2 设置超时时间

      通过API网关路由来访问用户服务,zuul默认路由规则 :http://zuul的Host地址:zuul端口/要调用的服务名/服务方法地址

      浏览器中打开http://localhost:5551/userservice/user/getall
      报错:
      This application has no explicit mapping for /error, so you are seeing this as a fallback.
      Tue Aug 07 17:49:01 CST 2018
      There was an unexpected error (type=Gateway Timeout, status=504).
      com.netflix.zuul.exception.ZuulException: Hystrix Readed time out

      

      这个错误是应为zuul的默认超时时间比较小,我们配置下zuul的超时时间,因zuul启用了ribbon的负载均衡,还需要设置ribbon的超时时间,注意ribbon的超时时间要小于zuul超时时间 。  

    zuul:
      host:
        connect-timeout-millis: 15000 #HTTP连接超时要比Hystrix的大
        socket-timeout-millis: 60000   #socket超时
    ribbon:
      ReadTimeout: 10000
      ConnectTimeout: 10000

      

      如有启用Hystrix,还需设置Hystrix的超时时间,注意Hystrix的超时时间要小于zuul超时时间

    hystrix:
      command:
        default:
          execution:
            timeout:
              enabled: true
            isolation:
              thread:
                timeoutInMilliseconds: 10000 #设置超时时间 10秒

      再通过网关调用服务,已成功返回数据。

      

      如需要在zuul做过滤、拦截等,可以参考官网文档:http://cloud.spring.io/spring-cloud-static/Finchley.SR1/single/spring-cloud.html#_router_and_filter_zuul
      在网关项目新建一个继承ZuulFilter的类,然后在该类中写过滤逻辑,譬如参数过滤  

    public class QueryParamPreFilter extends ZuulFilter {
        @Override
        public int filterOrder() {
            return PRE_DECORATION_FILTER_ORDER - 1; // run before PreDecoration
        }
    
        @Override
        public String filterType() {
            return PRE_TYPE;
        }
    
        @Override
        public boolean shouldFilter() {
            RequestContext ctx = RequestContext.getCurrentContext();
            return !ctx.containsKey(FORWARD_TO_KEY) // a filter has already forwarded
                    && !ctx.containsKey(SERVICE_ID_KEY); // a filter has already determined serviceId
        }
        @Override
        public Object run() {
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            if (request.getParameter("sample") != null) {
                // put the serviceId in `RequestContext`
                ctx.put(SERVICE_ID_KEY, request.getParameter("foo"));
            }
            return null;
        }
    }

      

      2.客户端通过API网关调用服务

      2.1 .net core调用网关服务

       在VS中新建一个控制台程序,使用HttpClient来调用服务  

    class Program
    {
        static void Main(string[] args)
        {
            string userServiceUrl = "http://localhost:5551/userservice/user/";//通过网关地址来调用服务
            var client = new HttpClient { BaseAddress = new Uri(userServiceUrl) };
            HttpResponseMessage response = client.GetAsync("getall").Result;
            string responseStr = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine(responseStr);
            Console.ReadKey();
        }
    }

      启动控制台,成功返回用户信息的Json数据。

      

      至此API网关配置完成。 

      关于安全及认证授权,.net core使用较多的是IdentityServer4,因我们现使用的系统已有自己的授权认证方法(时间戳来做有效时间,用户名+密码或APIKey的签名做验证),暂时不加IdentityServer4。

  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/townsend/p/9580490.html
Copyright © 2011-2022 走看看