記事ディレクトリ
0. 学習目標
1.Nacos構成管理
Nacos は登録センターであるだけでなく、構成管理にも使用できます。
1.1. 統合構成管理
デプロイされるマイクロサービスのインスタンスが数十、数百に達すると、マイクロサービスの構成を 1 つずつ変更すると、気が狂い、間違いが発生しやすくなります。すべてのインスタンスの構成を一元管理できる、統合された構成管理ソリューションが必要です。
一方では、Nacos は構成を集中管理でき、他方では、構成が変更された場合、適時にマイクロサービスに通知して構成のホット アップデートを実現できます。
1.1.1. nacos に設定ファイルを追加する
nacos で構成を管理するにはどうすればよいですか?
まず新しい構成を作成し、それを nacos に渡して管理します。
次に、ポップアップ フォームに構成情報を入力します。
ID は実際には構成ファイルの名前であり、一意である必要があり、厳密に形式に従って名前を付ける必要があります。サフィックスの完全名は実際には
環境です: dev、test、prod
注: プロジェクトのコア構成は、ホット アップデート構成が必要な場合にのみ nacos によって管理する必要があります。変更されない一部の構成は、マイクロサービス内でローカルに保存することをお勧めします。
[公開] をクリックして、新しく作成された構成ファイルを確認します。これは、以前に作成したときに開発クラスターの下に作成されているため、構成は開発クラスターの下にあります。
詳細をクリックして詳細情報を表示します。
コースとの一貫性を保つために、パブリック クラスターを削除して、新しいクラスターを作成します。
1.1.2. マイクロサービスから設定をプルする
プロジェクトの起動を完了するには、マイクロサービスは nacos で管理されている構成をプルし、それをローカルの application.yml 構成 (完全な構成ファイル) とマージする必要があります。
最初に nacos の設定を読み取り、次に application.yml の設定を読み取るように読み取り順序が変更されましたが、nacos のアドレスは application.yml に配置されたままです。どうすればよいですか? あれは:
しかし、application.yml がまだ読み込まれていない場合、nacos のアドレスはどうやってわかるのでしょうか?
したがって、Spring では新しい構成ファイルbootstrap.yamlファイルが導入され、application.yml の前に読み取られます。プロセスは次のとおりです。
1) nacos-config 依存関係を導入する
まず、user-service サービスに nacos-config のクライアント依存関係を導入します。
Q: なぜ user-service なのか?
回答: user-service マイクロサービスを例として使用します。以前に作成した nacos 構成の名前 (userservice-dev.yaml) を見ると、それがホット アップデートであることがわかります。ユーザーサービスマイクロサービスの構成。
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2) bootstrap.yaml を追加します
次に、次の内容を含むbootstrap.yamlファイルをuser-service に追加します。
ファイル名はbootstrap.yaml である必要があります。これは特別なファイルです。アイコン上の雲を見ると、特別なファイルであることがわかります。
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: localhost:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
ここで、nacos アドレスは spring.cloud.nacos.server-addr に従って取得され、次に次に従って取得されます。
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
ファイル ID として、構成を読み取ります。
この例では、次のようになりますuserservice-dev.yaml
。
- nacos には繰り返し設定がいくつかあるので、削除 (またはコメント化) できることに注意してください。
3) nacos 設定の読み取り
ビジネス ロジックを user-service の UserController に追加し、pattern.dateformat 構成を読み取ります。
コントローラーと Java コードでは、yml 設定を読み取って直接挿入するのが非常に簡単です (アプリケーション設定は Bean として作成され、IOC コンテナーで管理されます)。
完全なコード:
package cn.whu.user.web;
import cn.whu.user.pojo.User;
import cn.whu.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
//controller里读取配置很简单 直接注入 (application配置是会创建成bean被放在IOC容器中管理的)
@Value("${pattern.dateformat}") // 注意这个配置是写在nacos配置中心的,并不在本地 (本地只是在bootstrap里配置了该如何读取他 只有正常读到了,这里才能获取到他)
private String dateformat;
// 写一个controller方便查看有没有读取到
@GetMapping("now") //不写/默认会给你加上/
public String now(){
String value = "格式: " + dateformat;
DateTimeFormatter pattern = DateTimeFormatter.ofPattern(dateformat);
String res = "时间: "+LocalDateTime.now().format(pattern);
return value + "\n" + res;
}
}
ページにアクセスすると、次の効果がわかります。
http://localhost:8081/user/now
- まとめ
1.2. ホットアップデートの設定
私たちの最終的な目標は、nacos の構成を変更して、マイクロサービスが再起動せずに構成を有効にできるようにすること、つまり構成のホット アップデートです。
ブラウザ側、nacos コンソール、構成を変更します。
次に、「公開」-「公開の確認」をクリックします。
ブラウザを更新してもホット アップデートはありません。これは、ホット アップデートを実現するには、コードを少し変更し、いくつかの構成を行う必要があることを示しています。
構成のホット アップデートを実現するには、次の 2 つの方法を使用できます。
yml 設定を読み取る方法は 2 つあり ( springBoot コースの内容-2.3 yaml データの読み取り)、対応するホット アップデート設定にも 2 つの設定があります。
1.2.1. 方法 1 (@Value の直接注入)
@Value によって挿入された変数が配置されているクラスにアノテーションを追加します@RefreshScope
。
アノテーションを追加した後にサービスを再起動し、nacos で yml 設定を変更し、再起動せずに直接更新すると、実際にホット アップデートが実現できることがわかります。
1.2.2. 方法 2 (pojo に注入)
@Value アノテーションの代わりに @ConfigurationProperties アノテーションを使用します。
user-service サービスで、patternern.dateformat プロパティを読み取るクラスを追加します。
cn.whu.user.config.PatternProperties
package cn.whu.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data //提供Get/Set方法 spring就能自动帮我们注入属性值了 (否则私有的,框架也访问不到(业务框架也不可能对你的类进行暴力反射))
@Component //做成spring Bean, IOC容器里有, 那么任何地方就都可以注入他后使用他了
@ConfigurationProperties(prefix = "pattern") // 约定优于配置: 前缀名和属性名拼在一起和配置文件里的配置名一致,就能完成属性的自动注入
public class PatternProperties {
private String dateformat;//和nacos的yml配置文件里的名称保持一致
}
UserController で @Value の代わりにこのクラスを使用します (または、Bean にこのクラスがある場合は、このクラスを直接挿入します)。
注: @RefreshScope アノテーションを併用しなくても構成のホットアップデートは実現できます
完全なコード:
package cn.whu.user.web;
import cn.whu.user.config.PatternProperties;
import cn.whu.user.pojo.User;
import cn.whu.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
//@RefreshScope
public class UserController {
@Autowired
private UserService userService;
@Autowired
private PatternProperties patternProperties;
// 写一个controller方便查看有没有读取到
@GetMapping("now") //不写/默认会给你加上/
public String now(){
String value = "格式: " + patternProperties.getDateformat();
DateTimeFormatter pattern = DateTimeFormatter.ofPattern(patternProperties.getDateformat());
String res = "时间: "+LocalDateTime.now().format(pattern);
return value + "\n" + res;
}
}
コース推奨の使用方法 2: @ConfigurationProperties で POJO に設定を直接注入し、@Component を Bean にして POJO に直接注入すると、POJO は自動的にホットアップデートされ、他のアノテーションを追加する必要はありません。
悪くない
1.3. 設定の共有
実際、マイクロサービスが開始されると、nacos に移動して複数の構成ファイルを読み取ります。次に例を示します。
-
[spring.application.name]-[spring.profiles.active].yaml
例: userservice-dev.yaml -
[spring.application.name].yaml
、例: userservice.yaml
[spring.application.name].yaml
環境を含まないため
(簡単に理解すると、この構成ファイルの名前には環境情報が含まれていないため、どの環境であっても、この構成ファイルはマイクロサービスの開始時に読み込まれます)
ケースを通して構成共有をテストしてみましょう
1) 環境共有構成を追加する
nacos に userservice.yaml ファイルを追加します。
「公開」-「リリースの確認」をクリックします
2) ユーザーサービスで共有設定を読み取る
ユーザー サービス サービスで、PatternProperties クラスを変更し (プロパティを追加するだけです)、新しく追加されたプロパティを読み取ります。
user-service サービスで、UserController を変更し、メソッドを追加します。
@GetMapping("prop")
public PatternProperties prop(){
return patternProperties;
}
3) 異なるプロファイルを使用して 2 つの UserApplication を実行します。
スタートアップ項目 UserApplication2 を変更し、そのプロファイル値を変更します。
2 番目のマイクロサービスが主導権を持って読み取りを行っていることがわかりますuserservice-test.yaml
が、
最初のものは自然にuserservice-dev.yaml
読むものです
このように、UserApplication(8081)で使用されるプロファイルはdev、UserApplication2(8082)で使用されるプロファイルはtestとなります。
UserApplication と UserApplication2 を起動します
http://localhost:8081/user/propにアクセスすると、結果は次のようになります。
http://localhost:8082/user/propにアクセスすると、結果は次のようになります。
開発環境とテスト環境の両方が属性 envSharedValue の値を読み取っていることがわかります。
4) 共有の優先順位を設定する
nacos とサービスローカルが同時に同じ属性を持つ場合、優先度は高と低に分けられます。
IDEA のユーザー サービスの application.yml で同じプロパティを設定し、テストを続行します。
pattern:
name: 本地环境local
envSharedValue: 本地环境共享值
POJOに属性を追加することで取得できます。
テスト結果は次のとおりです。
nacosで設定する
name はローカルでのみ使用できるため、ローカルの値が表示されますが、envSharedValue はローカルと nacos で使用できるため、当然、nacos 設定がより高い優先度で表示されます。これは、上記の設定優先度が正しいことも証明します。
詳細にテストすることもできます。nacos コンソールで userservice.yaml に名前を書き込むと、ローカル名が上書きされ、
次に userservice-dev.yaml に名前を書き込むと、userservice.yaml の名前が上書きされます。
- まとめ
1.4. Nacos クラスターの構築
Nacosの本番環境ではクラスタ状態でデプロイする必要があり、デプロイ方法についてはプレコース資料のドキュメントを参照してください。
リンク: https://pan.baidu.com/s/1ohYXtEMJIBi6fUG45Vyg3g
抽出コード: v8s5
または、このブログを直接参照してください: https://blog.csdn.net/hza419763578/article/details/130744500
2. リモート通話を装う
まず、RestTemplate を使用してリモート呼び出しを開始するために使用したコードを見てみましょう。
以下の問題があります。
• コードの可読性が低く、一貫性のないプログラミング エクスペリエンス
• 複雑なパラメータを含む URL は保守が困難です
Feign は宣言型 http クライアントです。公式アドレス: https://github.com/OpenFeign/feign
その役割は、http リクエストの送信をエレガントに実装し、上記の問題を解決するのに役立ちます。
2.1. Feign が RestTemplate を置き換える
Fegin を使用する手順は次のとおりです。
1) 依存関係を導入する
order-service サービスの pom ファイルに偽の依存関係を導入します。
<!-- feign客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
-starter- はブート開始の依存関係、自動アセンブリです。
2) 注釈を追加する
order-service のスタートアップ クラス (OrderApplication) にアノテーションを追加して、Feign の機能を有効にします。@EnableFeignClients
3) Feign のクライアントを書く
次の内容を含む新しいインターフェイスを order-service に作成します。
cn.whu.order.clients.UserClient
package cn.whu.order.clients;
import cn.whu.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
@FeignClient アノテーションにより、クラスを springIOC コンテナ管理用の Bean として作成できるようになり、任意の Java コードを挿入してアクセスできるようになります。
元の URL メソッドの情報と比較すると、すべての情報が揃っているため、インターフェイス メソッドを呼び出すだけで済み、非常に便利です。
このクライアントは主にSpringMVC アノテーションに基づいていますリモート呼び出しに関する情報を宣言する、例えば:
- サービス名: ユーザーサービス
- リクエストメソッド:GET
- リクエストパス: /user/{id}
- リクエストパラメータ: 長い ID
- 戻り値の型: ユーザー
このように、Feign は、RestTemplate を使用せずに http リクエストを送信するのに役立ちます。
4) テスト
order-service の OrderService クラスの queryOrderById メソッドを変更し、RestTemplate の代わりに Feign クライアントを使用します。
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.利用Feign发起http请求,查询用户
User user = userClient.findById(order.getUserId());
// 3.封装user到order
order.setUser(user);
// 4.返回
return order;
}
}
よりエレガントに見えませんか。
1. nacos クラスターが以前に構成されている場合、ユーザー サービス登録センターがポート 80 に変更される可能性があることに注意してください。これは、8848 に戻す必要があります (そうしないと、登録センターで維持されません。相互に呼び出す方法)。 user-service bootstrap.yml
server-addr: localhost:8848 # Nacos地址
2 では、名前空間がマイクロサービスを分離するため、order-service の application.yml をコメントアウトする必要があります。
通常のアクセス
さらに進んで、すべての負荷分散構成をコメントアウトします。
order-service の application.yml
order-service の OrderApplication
Feign の自動負荷分散がここに反映されており、負荷分散を有効にするために @LoadBalanced アノテーションを追加する必要はありません。
コード内に負荷分散構成が存在しない場合は、再度実行してください。
ロードバランシングがまだ存在し、均等に分散されていることがわかり、ロードバランシングが自動的に実現されます(追加のアノテーションを追加する必要はありません)。
しかし、まだクラスターの存在を認識できないようです。すべてのクラスターは設定され、コメントアウトされています。UserApplication3 を除くデフォルトクラスターにあるはずですが、このクラスター (デフォルトクラスター) のマイクロサービスにアクセスする優先度はありません。 [Feign は負荷分散を有効にするために追加のメモを追加する必要はありませんが、nacos クラスターが関係する場合は、nacos 負荷分散ポリシー構成の行を追加する必要があります]
例: nacos 負荷分散戦略の構成を開くと、クラスターを認識し、このクラスター内のマイクロサービスへのアクセスを優先して (デフォルト)、ブラウザーで
http ://localhost:8080/order/101 にアクセスできます。 、ShangHai クラスターの UserApplication3 は呼び出されず、ログの行は出力されません。
リボンは見せかけで統合されている必要があり、確かにチェックがあります
5) まとめ
Feign を使用する手順:
①依存関係を導入する
② @EnableFeignClients アノテーションを追加
③ FeignClientインターフェースを書く
④ RestTemplateの代わりにFeignClientに定義されたメソッドを使用する
2.2. カスタム構成
基本的に、Boot の自動アセンブリのデフォルト構成を使用するだけで十分ですが、Boot を使用するとデフォルト構成をオーバーライドできます。
Feign は、次の表に示すように、多くのカスタム構成をサポートできます: (これら 5 つの例だけでなく、5 つの例のみ)
タイプ | 効果 | 説明する |
---|---|---|
偽りのロガーレベル | ログレベルの変更 | 4 つの異なるレベルが含まれます: NONE、BASIC、HEADERS、FULL |
feign.codec.Decoder | 応答結果のパーサー | json 文字列を Java オブジェクトに解析するなど、http リモート呼び出しの結果を解析します。 |
feign.codec.Encoder | リクエストパラメータのエンコーディング | http リクエスト経由で送信するためのリクエスト パラメータをエンコードする |
ふりをする。契約 | サポートされている注釈形式 | デフォルトはSpringMVCのアノテーションです |
ふりをする。リトライアー | 失敗時の再試行メカニズム | リクエスト失敗時の再試行メカニズム。デフォルトは「いいえ」ですが、リボンの再試行が使用されます。 |
偽装の最下層はリボンであり、これは失敗時の再試行メカニズムを備えていることに相当します。
通常はデフォルト値で十分ですが、カスタマイズする場合は、カスタム @Bean を作成してデフォルト Bean をオーバーライドするだけです。
以下では、例としてログを使用して、構成をカスタマイズする方法を示します。
2.2.1. 設定ファイル方式
構成ファイルに基づいて feign のログ レベルを変更すると、単一のサービスを対象にすることができます。
feign:
client:
config:
userservice: # 针对某个微服务的配置
loggerLevel: FULL # 日志级别
すべてのサービスをターゲットにすることもできます。
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
Consumer Order-Service の application.yml の下部に新しい設定を追加し、
再起動後、再度アクセスしてログを確認します
リモート通話の偽ログを見ることができます
05-18 16:01:25:642 INFO 113788 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
05-18 16:01:25:642 INFO 113788 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
05-18 16:01:25:644 INFO 113788 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
05-18 16:01:25:666 INFO 113788 --- [nio-8080-exec-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
05-18 16:01:25:748 INFO 113788 --- [nio-8080-exec-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
05-18 16:01:25:752 DEBUG 113788 --- [nio-8080-exec-1] c.whu.order.mapper.OrderMapper.findById : ==> Preparing: select * from tb_order where id = ?
05-18 16:01:25:760 DEBUG 113788 --- [nio-8080-exec-1] c.whu.order.mapper.OrderMapper.findById : ==> Parameters: 101(Long)
05-18 16:01:25:768 DEBUG 113788 --- [nio-8080-exec-1] c.whu.order.mapper.OrderMapper.findById : <== Total: 1
05-18 16:01:25:771 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] ---> GET http://userservice/user/1 HTTP/1.1
05-18 16:01:25:771 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] ---> END HTTP (0-byte body)
05-18 16:01:25:800 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] <--- HTTP/1.1 200 (27ms)
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] connection: keep-alive
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] content-type: application/json
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] date: Thu, 18 May 2023 08:01:25 GMT
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] keep-alive: timeout=60
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] transfer-encoding: chunked
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById]
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] {
"id":1,"username":"柳岩","address":"湖南省衡阳市"}
05-18 16:01:25:801 DEBUG 113788 --- [nio-8080-exec-1] cn.whu.order.clients.UserClient : [UserClient#findById] <--- END HTTP (59-byte body)
ログレベルは次の 4 種類に分類されます。
- NONE: ログ情報を記録しません。これがデフォルト値です。(Feign のログです)
- BASIC: リクエストメソッド、URL、レスポンスステータスコード、実行時間(httpリクエストが送信された時間、終了時間、所要時間)のみを記録します。
- HEADERS: BASICをベースに、リクエストとレスポンスのヘッダ情報を追加記録します。
- FULL: ヘッダー情報、リクエスト本文、メタデータを含む、すべてのリクエストとレスポンスの詳細を記録します。
2.2.2. Javaコードメソッド
Java コードに基づいてログ レベルを変更することもできます。最初にクラスを宣言し、次に Logger.Level オブジェクトを宣言します。
cn.whu.order.config.DefaultFeignConfiguration.java
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC; // 日志级别为BASIC
}
}
このクラスにはアノテーションが追加されていないため、デフォルトでは有効になりません。有効にする方法は
2 つあります。
グローバルに有効にしたい場合は、スタートアップ クラスの @EnableFeignClients アノテーションに追加します。defaultConfiguration=
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
元の yml の設定に注釈を付けて再度テストすると、BASIC レベルの Feign ログしかないことがわかりました。
ローカルで有効な場合は、対応する (xxxClient インターフェイス) @FeignClient アノテーションに入れます。configuration=
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)
OrderApplication の設定をコメント アウトし、
サービス テストを再起動すると、BASIC レベルのログがまだ存在していることがわかります。
- まとめ
ログ レベル: デバッグには FULL を使用し、通常の使用には NONE、BASIC を使用します。
2.3. 偽装使用の最適化
Feign の最下層は http リクエストを開始し、他のフレームワークに依存します。その基礎となるクライアント実装には次のものが含まれます。
•URLConnection: デフォルトの実装、接続プールはサポートされません (JDK が付属していますが、パフォーマンスは非常に低く、新しい TCP 接続が作成されるたびに、解放時に 3 回のハンドシェイクと 4 回の分割が発生します)。
• Apache HttpClient: 接続プールをサポート
• OKHttp: 接続プールのサポート
したがって、Feign のパフォーマンスを向上させる主な手段は、デフォルトの URLConnection の代わりに接続プールを使用することです。
ここでは、Apache の HttpClient を使用してデモンストレーションします。(Spring の最下層もデフォルトです)
1) 依存関係を導入する
order-service の pom ファイルに Apache の HttpClient 依存関係を導入します。
<!--httpClient的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2) 接続プールを構成する
order-service の application.yml に設定を追加します。
feign:
client:
config:
default: # default全局的配置
loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
httpclient:
enabled: true # 开启feign对HttpClient的支持
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
次に、FeignClientFactoryBean のloadBalance メソッドのポイントをブレークします (Shfit をダブルクリックして FeignClientFactoryBean を検索します)。
デバッグ モードで order-service サービスを開始します。ここにクライアントが表示されます。最下層は Apache HttpClient です。
-
要約すると、Feign の最適化は次のようになります。
1. ログレベルとしてベーシックを使用してみます。
2. URLConnection の代わりにHttpClientまたは OKHttp を使用します。
① feign-httpClient 依存関係を導入する
② 設定ファイルは httpClient 機能を有効にし、接続プールのパラメータを設定します。
2.4. ベストプラクティス
いわゆるベストプラクティスとは、使用プロセスで要約されたエクスペリエンス、つまりそれを使用するための最良の方法を指します。
自己調査によると、Feign のクライアントはサービス プロバイダーのコントローラー コードと非常によく似ていることがわかりました。
偽のクライアント:
ユーザーコントローラー:
この繰り返しのコーディングを簡素化する方法はあるでしょうか?
2.4.1. 継承方法
同じコードは継承を通じて共有できます。
1) API インターフェースを定義し、定義メソッドを使用し、SpringMVC アノテーションに基づいてステートメントを作成します。
2) Feign クライアントとコントローラーの両方がこのインターフェイスを継承します。
アドバンテージ:
- 単純
- コードシェア
欠点:
-
サービスプロバイダーとサービスコンシューマーは密接に結合されています
-
パラメータリストのアノテーションマッピングは継承されないため、メソッド、パラメータリスト、アノテーションをコントローラで再度宣言する必要があります。
2.4.2. 抽出方法
Feign の Client を独立したモジュールとして抽出し、インターフェイスに関連する POJO とデフォルトの Feign 設定をこのモジュールに組み込み、すべてのコンシューマーに提供します。
たとえば、UserClient、User、および Feign のデフォルト構成はすべて feign-api パッケージに抽出され、この依存関係パッケージを参照することですべてのマイクロサービスを直接使用できます。
- まとめ
2.4.3. 抽出ベースのベストプラクティスの実装
1) 抽出
まず、feign-api という名前のモジュールを作成します。
プロジェクトの構造:
feign-api で、feign のスターター依存関係を導入します。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
次に、order-service に記述された UserClient、User、および DefaultFeignConfiguration がすべて feign-api プロジェクトにコピーされます (パッケージを直接コピーするだけです)。
UserClient のユーザー パッケージが再インポートされることに注意してください。パッケージ構造名が変更されたためです。
order-service 内の関連パッケージと pojo は直接削除できることがわかりました。
下の赤枠の直接削除ですが、心配しないでください。
削除後、order-service の OrderService クラスはエラーを報告しますが、心配せずに続行してください。
2) order-service で feign-api を使用する
まず、order-service 内の UserClient、User、DefaultFeignConfiguration などのクラスまたはインターフェイスを削除します。
order-service の pom ファイルに feign-api の依存関係を導入します。
<dependency>
<groupId>cn.whu.demo</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
order-service の上記 3 つのコンポーネントに関連するパッケージのインポート部分をすべて変更し、feign-api でパッケージをインポートするように変更します。
1. Order.java のユーザー
2. OrderService.java のユーザーと UserClient
3) テストを再開します
再起動後、サービスがエラーを報告したことが判明しました。
コンパイルでは、クラスが存在することを示すエラーは報告されませんが、実行では、クラスに対応する Bean が見つからないというエラーが報告されます。これは、Spring が UserClient クラスをまったくスキャンしていないため、オブジェクトを作成できないことを示します対応する Bean を注入できません
これは、UserClient が cn.whu.feign.clients パッケージの下にあるためです。
order-service の @EnableFeignClients アノテーションは、同じパッケージ内ではなく cn.whu.order パッケージの下にあるため、UserClient をスキャンできません。
デフォルトでは、cn.whu.order パッケージとそのサブパッケージ内のクラスのみがスキャンされ、オブジェクトが作成されます。
springBoot は、jar パッケージ内のクラスもスキャンしてインポートします。パッケージ構造がこのプロジェクトのプロジェクト構造と一致している限り、スキャンされます。パッケージ構造が異なるため、自動的にスキャンできません
。手動で設定してスキャンさせます
4) パッケージのスキャンの問題を解決する
方法 1:
Feign がスキャンする必要があるパッケージを指定します。
@EnableFeignClients(basePackages = "cn.whu.feign.clients")
方法 2:
ロードする必要があるクライアント インターフェイスを指定します。
@EnableFeignClients(clients = {
UserClient.class})
2 番目の方法を使用することをお勧めします
3.ゲートウェイサービス ゲートウェイ
Spring Cloud Gateway は、Spring 5.0、Spring Boot 2.0、Project Reactor などのリアクティブ プログラミングやイベント フロー技術をベースに開発された Spring Cloud の新しいプロジェクトで、シンプルかつ効果的な統合 API ルート管理手法を提供することを目的としています。
3.1. ゲートウェイが必要な理由
ゲートウェイはサービスの門番であり、すべてのマイクロサービスの統一された入り口です。
ゲートウェイの中核となる機能特性は次のとおりです。
- リクエストルーティング
- アクセス制御
- 制限する
アーキテクチャ図:
アクセス制御: マイクロサービスのエントリ ポイントとして、ゲートウェイはユーザーがリクエストに適格かどうかを確認し、適格でない場合はリクエストをインターセプトする必要があります。
ルーティングと負荷分散: すべてのリクエストは最初にゲートウェイを通過する必要がありますが、ゲートウェイはビジネスを処理せず、特定のルールに従ってリクエストをマイクロサービスに転送します。このプロセスはルーティングと呼ばれます。もちろん、ルーティング対象のサービスが複数ある場合には、負荷分散も必要になります。
電流制限: リクエスト トラフィックが多すぎる場合、ゲートウェイは、過度のサービス プレッシャーを避けるために、ダウンストリーム マイクロサービスが受け入れることができる速度に従ってリクエストを解放します。
Spring Cloud には 2 種類のゲートウェイ実装があります。
- ゲートウェイ
- ズル
Zuul はサーブレットベースの実装であり、ブロッキング プログラミングに属します。Spring Cloud Gateway は Spring 5 で提供される WebFlux をベースにしており、応答性の高いプログラミングの実装であり、パフォーマンスが向上しています。
- まとめ
3.2. ゲートウェイのクイックスタート
次に、ゲートウェイの基本的なルーティング機能を説明します。基本的な手順は次のとおりです。
- SpringBoot プロジェクト ゲートウェイを作成し、ゲートウェイの依存関係を導入する
- スタートアップクラスを書く
- 基本的な構成とルーティング ルールを作成する
- テスト用のゲートウェイ サービスを開始する
1) ゲートウェイ サービスを作成し、依存関係を導入する
サービスを作成します。
依存関係をインポートします。
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2) スタートアップクラスを書く
package cn.whu.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
3) 基本的な設定とルーティング ルールを作成します。
次の内容を含む application.yml ファイルを作成します。
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称 (这也是一个微服务而已)
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称 (lb:loadBalance)
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
Path
ルールに一致するすべてのリクエストを、uri
パラメーターで指定されたアドレスにプロキシします。(エージェントは yml で自分自身を設定することもできます)
/user/**
この例では、最初のリクエストをプロキシし、 lb://userservice
lb はロード バランシングであり、サービス名に従ってサービス リストをプルし、ロード バランシングを実現します。
4) テストを再開します
GatewayApplication.Main を開始します
ゲートウェイを再起動します。http://localhost:10010/user/1 にアクセスすると、ルールに準拠し/user/**
、リクエストが uri: http://userservice/user/1 に転送され、結果が取得されます。
同様に、http://localhost:10010/order/101にアクセスできます。
5) ゲートウェイルーティングのフローチャート
アクセスプロセス全体は次のとおりです。
要約:
ゲートウェイの構築手順:
-
プロジェクトを作成し、nacos サービスの検出とゲートウェイの依存関係を導入します。
-
基本的なサービス情報、nacos アドレス、ルーティングを含む application.yml を構成します。
ルーティング設定には次のものが含まれます。
-
ルート ID: ルートの一意の識別子
-
ルーティング宛先 (uri): ルーティングの宛先アドレス、http は固定アドレスを表し、lb はサービス名に基づく負荷分散を表します。
-
ルーティングアサーション(述語):ルーティングを判断するためのルール、
-
ルート フィルター (フィルター): リクエストまたはレスポンスを処理します。
次に、ルーティング アサーションとルーティング フィルターの詳細な知識を学習することに重点を置きます。
3.3. アサーションファクトリー
設定ファイルに記述するアサーション ルールは単なる文字列であり、Predicate Factory によって読み取られて処理され、ルーティング判断の条件に変換されます。
たとえば、Path=/user/** はパスに従って照合されます。このルールは次のように決定されます。
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory
クラスへ
処理のために、SpringCloudGateway にはこのようなアサーション ファクトリが 12 個以上あります。
Spring によって提供される 11 個の基本的な Predicate ファクトリを以下に示します。
名前 | 説明する | 例 |
---|---|---|
後 | ある時点以降のリクエストです | - 後=2037-01-20T17:42:47.789-07:00[アメリカ/デンバー] |
前に | ある時点より前のリクエストです | - Before=2031-04-13T15:14:47.433+08:00[アジア/上海] |
間 | 特定の 2 時点より前のリクエストです | - 間=2037-01-20T17:42:47.789-07:00[アメリカ/デンバー]、2037-01-21T17:42:47.789-07:00[アメリカ/デンバー] |
クッキー | リクエストには特定の Cookie が含まれている必要があります | - クッキー=チョコレート、ch.p |
ヘッダ | リクエストには特定のヘッダーが含まれている必要があります | - ヘッダー=X-リクエストID、\d+ |
ホスト | リクエストは特定のホスト (ドメイン名) にアクセスするものでなければなりません | - ホスト= .somehost.org、 .anotherhost.org |
方法 | リクエストメソッドを指定する必要があります | - メソッド=GET,POST |
パス | リクエストのパスは指定されたルールに準拠する必要があります | - パス=/red/{セグメント}、/blue/** |
クエリ | リクエストパラメータには指定されたパラメータが含まれている必要があります | - クエリ=名前、ジャック、または - クエリ=名前 |
リモートアドレス | リクエスタの IP は指定された範囲内にある必要があります | - RemoteAddr=192.168.1.1/24 |
重さ | 重み付け処理 |
調べてください: 例:RemoteAddr は外部ネットワーク セグメントの IP をブロックでき、外部アクセスは許可しません。After は指定された時点以降にのみ
公式ルーティング ドキュメントをルーティングできます。
公式のDiplayに従ってプレイすることはできます
が、再起動後、ゲートウェイからorder-serviceマイクロサービスにアクセスしようとしてもアクセスできなくなります。レポート404: http://localhost:10010/order/101
が以前に変更され、再度アクセスできるようになります
。ただし、ゲートウェイからユーザー サービス マイクロサービスにアクセスすることは可能です: http://localhost:10010/user/1
最後から 4 番目のパスを使用します。
Pathのルーティング エンジニアリングを習得するだけで済みます。
- まとめ
3.4. フィルターファクトリー
リクエストはゲートウェイを経由してマイクロサービスに到達します。
それでは、ゲートウェイ内では何が起こっているのでしょうか? 前回の研究の後、少なくともアサーション ファクトリーのルートを通過する必要があることがわかりました。
実際には、ルーティング後にフィルターを通過する必要があります
GatewayFilter はゲートウェイに提供されるフィルターで、ゲートウェイに入るリクエストとマイクロサービスから返される応答を処理できます。
3.4.1. ルーティングフィルターの種類
Spring は 31 の異なるルート フィルター ファクトリを提供します。例えば:
名前 | 説明する |
---|---|
リクエストヘッダーの追加 | 現在のリクエストにリクエストヘッダーを追加します |
リクエストヘッダーの削除 | リクエストからリクエストヘッダーを削除します |
応答ヘッダーの追加 | 応答結果に応答ヘッダーを追加します。 |
レスポンスヘッダーの削除 | 応答結果から削除された応答ヘッダーがあります |
リクエストレートリミッター | リクエストの量を制限する |
現在、公式ウェブサイトは37のルーティングフィルターファクトリーに更新されています。
3.4.2. リクエストヘッダーフィルター
AddRequestHeader を例に挙げて説明します。
要件: userservice に入るすべてのリクエストにリクエスト ヘッダーを追加します。Truth=itcast は本当に素晴らしいです!
ゲートウェイ サービスの application.yml ファイルを変更し、ルート フィルタリングを追加するだけです。
形式は次のとおりです。
- AddRequestHeader=key, value # key是请求头名称 value是具体的值
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
filters: # 过滤器
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
現在のフィルターは userservice ルートの下に書き込まれるため、userservice にアクセスするリクエストに対してのみ有効です。
UserController を変更するメソッドをテストし、リクエスト ヘッダー パラメーターを取得して出力します。
次に、ゲートウェイ経由でアクセスします: http://localhost:10010/user/1
案の定、コンソールにはリクエスト ヘッダーが正常に追加されたことを示す出力が表示されます。
3.4.3. デフォルトのフィルター
すべてのルートに有効にしたい場合は、デフォルトでフィルター ファクトリを記述できます。形式は次のとおりです。
spring:
cloud:
gateway:
routes: # 网关路由配置
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
default-filters: # 默认(全局)过滤项 所有微服务的路由请求都会执行这个过滤器的操作
- AddRequestHeader=Truth, whu is freaking awesome!! # 添加请求头
GatewayApplication を再起動し、http://localhost:10010/user/1 に再度アクセスしても、コンソールには次の情報が表示されます。
3.4.4. 概要
フィルターの役割は何ですか?
① リクエストヘッダーの追加など、ルーティングリクエストまたはレスポンスを処理します。
② ルートの下に設定されたフィルタは、現在のルートのリクエストに対してのみ有効です
defaultFilters の役割は何ですか?
①全経路に有効なフィルタ
3.5. グローバルフィルター
前のセクションで学習したフィルターについて、ゲートウェイは 31 種類を提供しますが、各フィルターの役割は固定されています。リクエストをインターセプトして独自のビジネス ロジックを実行したい場合、それを行う方法はありません。
3.5.1. グローバルフィルター機能
GatewayFilter の役割は以前の defaultFilters と同じですが、defaultFilters はフィルタリング操作を実行するように構成されており、
GatewayFilter は必要なロジックを Java コードで柔軟に記述することができます。
グローバル フィルターの役割は、ゲートウェイに入るすべてのリクエストとマイクロサービス応答を処理することであり、これは GatewayFilter の役割と同じです。違いは、GatewayFilter は構成によって定義され、処理ロジックが固定されているのに対し、GlobalFilter のロジックは自分でコードを記述して実装する必要があることです。
定義方法は、GlobalFilter インターフェースを実装することです。
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono<Void>} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
フィルターにカスタム ロジックを記述して、次の機能を実現します。
- ログイン状態の判定
- 権限チェック
- スロットリングなどをリクエストします。
3.5.2. カスタムグローバルフィルター
要件: グローバル フィルターを定義し、リクエストをインターセプトし、リクエストのパラメーターが次の条件を満たしているかどうかを判断します。
-
パラメータに権限があるかどうか、
-
認可パラメータ値が admin かどうか
同時に満たされる場合は手放し、そうでない場合はブロックします
成し遂げる:
ゲートウェイでフィルターを定義します。
package cn.whu.gateway;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Order(-1) //过滤器优先级 值越小,优先级越高
@Component //做成bean才能生效
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取请求参数
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> params = request.getQueryParams();
// 2. 获取参数中的 authorization 参数
String auth = params.getFirst("authorization"); //get方法获取所有 getFirst获取第一个匹配的
// 3. 判断参数值是否等于 admin
if("admin".equals(auth)){
// 4. 是:放行
return chain.filter(exchange);
}
// 5. 否:拦截
// 5.1 拦截之前给出提示 提高用户体验 具体实现就是:
// 设置状态码
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//401未登陆 已经帮你定义好了各种枚举
// 5.2 拦截请求
return exchange.getResponse().setComplete();
}
}
ゲートウェイ マイクロサービスを再起動します - GatewayApplication
アクセス: http://localhost:10010/user/2 はブロックされています、レポート 401
アクセス: http://localhost:10010/user/2?authorization=admin は正常にアクセスできます
- まとめ
3.5.3. フィルターの実行順序
リクエストがゲートウェイに入ると、現在のルート フィルター、DefaultFilter、GlobalFilter の 3 種類のフィルターに遭遇します。
ルーティングを要求した後、現在のルーティング フィルター、DefaultFilter、および GlobalFilter がフィルター チェーン (コレクション) にマージされ、並べ替え後に各フィルターが順番に実行されます。
並べ替えのルールは何ですか?
- 各フィルターには int 型の順序値を指定する必要があります。順序値が小さいほど優先順位が高く、実行順序も高くなります。
- GlobalFilter は、 Ordered インターフェースを実装するか、独自に指定した @Order アノテーションを追加することで順序値を指定します。
- ルーティングフィルターとdefaultFilterの順序はSpringで指定されており、デフォルトでは宣言の順序に従って1から増加する。
- フィルタの順序値が同じ場合、defaultFilter > ルーティングフィルタ > GlobalFilter の順で実行されます。
宣言順序は yml 構成ファイル内の構成の順序を指し、ルーティング フィルターとdefaultFilterはそれぞれ 1 からカウントされます
。
デフォルト フィルタとルーティング フィルタの最下層は GateWayFilter です。
グローバル フィルタは GlobalFilter で、見た目はまったく異なりますが、FilteringWebHandler.java には GatewayFilterAdapter があり、アダプタ モードを通じて GlobalFilter を GateWayFilter に適応させます
。上図の 3 つのフィルター どちらも同じタイプのGateWayFilterと見なすことができるため、コレクション内で並べ替えることができます
詳細については、ソース コードを参照してください。
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()
方法としては、まずdefaultFiltersをロードし、次に特定のルートのフィルタをロードしてマージします。
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()
このメソッドはグローバル フィルターをロードし、前のフィルターとマージした後の順序に従って並べ替え、フィルター チェーンを編成します。
- まとめ
3.6. クロスドメインの問題
3.6.1. クロスドメイン問題とは
クロスドメイン: 一貫性のないドメイン名はクロスドメインであり、主に次のようなものがあります。
-
異なるドメイン名: www.taabao.com、www.taabao.org、www.jd.com、miaosha.jd.com
-
同じドメイン名、異なるポート: localhost:8080 と localhost8081
クロスドメインの問題: ブラウザーは、リクエストの発信者がサーバーに対してクロスドメイン Ajax リクエストを行うことを禁止しており、リクエストはブラウザーによって傍受されます。
解決策: CORS、これは以前に学習したはずなので、ここでは繰り返しません。知らない友達はhttps://www.ruanyifeng.com/blog/2016/04/cors.htmlをチェックしてください。
3.6.2. クロスドメインの問題をシミュレートする
リンク: https://pan.baidu.com/s/1ohYXtEMJIBi6fUG45Vyg3g
抽出コード: v8s5
プレコース資料のページ ファイルを見つけます。
tomcatやnginxなどのWebサーバーに入れて起動し、アクセスします。(これは別のサーバーであることに注意してください。主にurl(ip:端口)
同じサーバーではないことを確認するためです)
ブラウザのコンソールに次のエラーが表示されます。
localhost:8090 から localhost:10010 にアクセスすると、ポートが異なります。これは明らかにクロスドメイン要求です。
3.6.3. クロスドメインの問題の解決
ゲートウェイ サービスの application.yml ファイルに、次の構成を追加します。
spring:
cloud:
gateway:
# 。。。
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题 (浏览器会先去询问服务器让不让这个请求跨域,这个询问请求默认会被拦截,但是肯定不能被拦截,此行配置true就是不拦截这个询问请求)
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息 (*表示一切请求头)
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
テスト方法は?
フロントエンドがなく、Tomcat のポート 8080 が占有されている場合は、新しいブート プロジェクトを作成し、別のポートを
apply.ymlに設定できます。
server:
port: 8089
その中でもindex.hmtlは非常にシンプルで、ajaxでクロスドメインリクエストを送信するだけです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<pre>
spring:
cloud:
gateway:
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
- "http://www.leyou.com"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
</pre>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.get("http://localhost:10010/user/1?authorization=admin")
.then(resp => console.log(resp.data))
.catch(err => console.log(err))
</script>
</html>
Web サービスを開始し、http://localhost:8090/にアクセスします。
F12 を押してエラーを見つけます
次に、ゲートウェイに構成を追加し、ゲートウェイを再起動して、http://localhost:8090/にアクセスします。
ブラウザのクロスドメイン Ajax リクエストは成功しました