升級微服務架構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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM