1. 基本的な紹介
各マイクロサービスのアドレスは変更される可能性があるため、直接アドレスを公表することはできず、セキュリティ、高結合性、低結合性の設計に基づき、内部システムと外部システムを分離する必要があります。外部リクエストの処理専用のコンポーネント、つまりサービス ゲートウェイが必要です。API ゲートウェイの定義は、オブジェクト指向設計パターンのファサード パターンに似ており、マイクロサービス アーキテクチャ システム全体のファサードと同様に、すべての外部クライアント アクセスをスケジュールし、それを通じてフィルター処理する必要があります。API ゲートウェイは、リクエスト ルーティング、ロード バランシング、検証フィルタリング、リクエスト転送時のヒューズ メカニズム、サービス アグリゲーションなどの機能を実装する必要があります。
Spring Cloud には、Zuul と Spring Cloud Gateway という 2 つの API Gateway の主な実装があります。Spring Cloud Zuul は、Neflix Zuul に基づいて実装された API ゲートウェイ コンポーネントです。Zuul の特徴:
- システムの統一された入口として、システム内の各マイクロサービスの詳細を保護します。
- インターフェース権限検証を実装する
- モニター
- 動的ルーティング
- 負荷分散
- 静的リソースの処理
Zuul の関数は基本的にフィルターに基づいて実装されます。フィルターにはいくつかの異なる種類があります。
- pre: リクエストがルーティングされる前に呼び出すことができます
- ルーティング: リクエストをルーティングするときに呼び出されます
- post: ルーティングフィルターとエラーフィルターの後に呼び出されます
- error: リクエストの処理中にエラーが送信されたときに呼び出されます。
2. 使用例
2.1 基本的な使い方
前回の記事で作成したEurekaサービスとProviderサービスを利用します。Spring Cloud Framework の学習 - 登録センター Spring Cloud Eureka
Zuul という名前の新しい Spring Boot プロジェクトを作成し、Spring Boot バージョン 2.2.4 を使用して、次の依存関係を pom.xml に追加します。
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>top.javahai.spring.cloud</groupId>
<artifactId>zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>zuul</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
注釈 @EnableZuulProxy をスタートアップ クラスに追加して、Zuul の API ゲートウェイ プロキシを有効にします。
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
application.propertiesで現在のZuulサービスの基本情報を構成します。
#服务名
spring.application.name=zuul
#服务端口号
server.port=2020
#注册中心url地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
登録センター、プロバイダー サービス、および zuul サービスを開始し、登録センター管理インターフェイスでサービスが正常に開始されたかどうかを確認してから、
アドレスhttp://localhost:2020/v1/provider/hello を要求すると、プロバイダー サービスが可能になります。 Zuul プロキシ経由でアクセスできます。
2.2 ルーティングと転送の構成
application.properties でルーティング ルールを構成する
zuul.routes.provider.path=/provider-test/**
zuul.routes.provider.service-id=provider
上記の構成により、/provider-test/** の一致ルールを満たすリクエストが定義され、処理のためにプロバイダー サービスに転送されます。
ルーティング ルールを構成するための上記の 2 行の構成は、1 行の構成に簡略化することもできます。
zuul.routes.provider=/provider-test/**
次の構成を通じて、ルールを満たすリクエストをルーティングし、特定の URL に転送できます。ここで、api-test-url はルート名です。パスと URL のマッピング関係のセットのルーティング名は同じである必要があります。
zuul.routes.api-test-url.path=/api-test/**
zuul.routes.api-test-url.url=http://localhost:8080/
2.3 リクエストフィルタリング設定
各クライアント ユーザーがマイクロサービス アプリケーションによって提供されるインターフェイスを要求すると、アクセス許可が制限されることが多く、システムはすべてのマイクロサービス インターフェイスをユーザーに対してオープンしません。これには、ゲートウェイで要求された権限検証を統一的に実装する必要があります。Zuul では、ZuulFilter 抽象クラスを継承し、それによって定義された 4 つの抽象メソッドを実装するだけで、リクエストのインターセプトとフィルタリングを完了できます。
以下は、リクエストをフィルタリングする前に、HttpServletRequest にユーザー名とパスワードのパラメーターがあるかどうか、およびそれらが要件を満たしているかどうかをチェックする単純な Zuul フィルターを実装しています。満たされている場合はルーティングされますが、満たされていない場合はアクセスが拒否され、401 エラーが返されます。
//注册到Spring容器中
@Component
public class PermissionFilter extends ZuulFilter {
/**
* 过滤器类型,它决定过滤器在请求的哪个生命周期中执行。
* 权限判断一般是pre,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 ctx = RequestContext.getCurrentContext();
//获取当前请求
HttpServletRequest request = ctx.getRequest();
String username = request.getParameter("username");
String password = request.getParameter("password");
//如果请求条件不满足的话,直接从这里给出响应
if (!"admin".equals(username) || !"123".equals(password)) {
//设置不进行路由
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
ctx.setResponseBody("非法访问");
}
return null;
}
}
Zuul を再起動し、ユーザー名とパスワードのパラメーターを指定してリクエストを送信します。そうしないと、リクエストは通過しません。
ユーザー名とパスワードのパラメータを指定してリクエストを送信します
3. さらなる設定
3.1 パスの無視
デフォルトでは、Zuul が Eureka に登録されると、Eureka に登録されているすべてのサービスが自動的にプロキシされます。特定のサービスのプロキシとして機能したくない場合は
、そのサービスを無視して次のように構成できます。
zuul.ignored-services=provider
上記の構成は、プロバイダー サービスが無視され、現時点ではプロバイダー サービスが自動的にプロキシされないことを示しています。
アドレスのクラスを無視します。
zuul.ignored-patterns=/**/hello/**
これは、リクエスト パスに hello が含まれる場合、それはプロキシではないことを意味します。
3.2 ルーティングプレフィックスの設定
zuul.prefix パラメーターを使用してプレフィックス情報をルーティング ルールにグローバルに追加し、プレフィックス構成例をルーティングに追加できます。
zuul.prefix=/v1
このように、すべてのリクエスト アドレスにはプレフィックス /v1 を付ける必要があります。
3.3 パス一致ルール
パス一致式は Ant スタイルで定義されており、Ant スタイルのパス式には合計 3 つのワイルドカードがあります。彼らです:
ワイルドカード | 説明する |
---|---|
? | 任意の 1 文字に一致します |
* | 任意の数の文字に一致しますが、複数レベルのディレクトリはサポートされません (たとえば、/user-service/* は /user-service/a/b に一致しません) |
** | 任意の数の文字に一致し、複数レベルのディレクトリをサポート |
3.4 Hystrix とリボンの構成
#设置API网关中路由转发请求的hystrixCommand执行超时时间,单位为毫秒
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=
#设置路由转发请求的时候,创建请求连接的超时时间
ribbon.ConnectTimeOut=
#设置路由转发请求的超时时间
ribbon.ReadTimeout=
参考:
1.「Spring Cloud Microservice 実戦」