前書き
Spring CloudはSpringのプロジェクトの1つであり、公式Webサイトのアドレス:http://projects.spring.io/spring-cloud/
Springは統合に最適であり、世界最高のフレームワークを採用して独自のプロジェクトに統合します。
Spring Cloudも同じですが、次のような現在非常に人気のあるテクノロジーのいくつかを統合しています。構成管理、サービスディスカバリ、インテリジェントルーティング、負荷分散、ヒューズ、制御バス、クラスターステータス等々。
関連する主なコンポーネントは次のとおりです
。Netflix
- ユーレカ:登録センター
- Zuul:サービスゲートウェイ
- リボン:負荷分散
- 偽物:サービスコール
- Hystrix:ヒューズ
- などなど
バージョン
SpringCloundとSpringBootバージョンの対応
列車を解放する | ブートバージョン |
---|---|
ホクストン | 2.2.x |
グリニッジ | 2.1.x |
フィンチリー | 2.0.x |
エッジウェア | 1.5.x |
ダルストン | 1.5.x |
親プロジェクトを作成する
マイクロサービスでは、複数のプロジェクトを同時に作成する必要があります。最初に親プロジェクトを作成します。後続のプロジェクトでは、Mavenの集約と継承を使用して、このプロジェクトを親として使用します。サブプロジェクトのバージョンと構成の統合管理
<!--聚合父工程-->
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<packaging>pom</packaging>
<relativePath/>
</parent>
<!--这里指定版本信息-->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<mapper.starter.version>2.1.5</mapper.starter.version>
<mysql.version>5.1.46</mysql.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<!--这里的import一定要记得加上,不然子工程报错-->
<scope>import</scope>
</dependency>
<!-- 通用Mapper启动器 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--lombok简化代码-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
サブプロジェクト
バージョン番号は、親プロジェクトによって統一された方法で管理されます。サブプロジェクトにバージョン番号を追加する必要はなく、依存関係を導入するだけです。
マイクロサービスでは、サービスプロデューサーとサービスコンシューマーが必要です
RESTスタイルのWebサービス
@RestController// 声明它是一个rest风格的控制器
@RequestMapping("/user")
@RefreshScope// 配置文件改变自动刷新属性
public class UserController {
// 注入service层
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
return userService.queryById(id);
}
}
マイクロサービスのスターター
@SpringBootApplication
これをマークする@SpringBootApplicationはSpringbootアプリケーションであり、マークされたクラスはメインプログラムSpringApplication.run(App.class、args)です。渡されるクラスApp.classは、@ SpringBootApplicationでマークされたクラスである必要があります。例えば:
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
@SpringBootApplicationは組み合わせアノテーションであり、その関数は次のアノテーションの組み合わせと同等
です。1。構成ファイルに対応する@SprootbootConfiguration(または@Configuration)構成クラス、本質的には@Componetですが、より意味があります。名前が知っていることを参照してください。意味
2. @ EnableAutoConfiguration:自動構成をオンにし、メイン構成クラスが配置されているパッケージのすべての注釈と、
3より下のすべての子孫パッケージをスキャンします。@ ComponentScan:スキャンするパッケージを構成します。
@SpringBootConfiguration
このアノテーションには、現在のクラスが構成クラスであることを宣言するために使用される@Configurationと同じ機能があります。@Beanアノテーションを使用してIOCコンテナー管理Beanを生成できます。ConsumerApplicationでBeanを定義し、UserControllerでConsumerApplicationを注入し
ます。
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[]args){
SpringApplication.run(ConsumerApplication.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
UserController:
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
String url = "http://localhost:9091/user/" + id;
return restTemplate.getForObject(url, User.class);
}
}
@EnableAutoConfiguration
@EnableAutoConfigurationは、自動構成を実現するためのspringbootのコアアノテーションです。このアノテーションを介して、Springアプリケーションに必要なBeanがコンテナーに注入されます。@EnableAutoConfigurationソースコードは、@ Importを介してImportSelectorAutoConfigurationImportSelectorの実装クラスを挿入します
@Import({
AutoConfigurationImportSelector.class})
AutoConfigurationImportSelector、このImportSelectorは、構成に従って必要なBeanを動的にロードすることを最終的に実現します。
動的ロードの実装方法を完了するためのAutoConfigurationImportSelectorのソースコードは次のとおりです。
// annotationMetadata 是@Import所在的注解,这里指定是EnableAutoConfiguration
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
try {
//加载XXConfiguration的元数据信息(包含了某些类被生成bean条件),继续跟进这个方法调用,就会发现加载的是:spring-boot-autoconfigure jar包里面META-INF的spring-autoconfigure-metadata.properties
AutoConfigurationMetadata autoConfigurationMetadata
= AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//获取注解里设置的属性,在@SpringBootApplication设置的exclude,excludeName属性值,其实就是设置@EnableAutoConfiguration的这两个属性值
AnnotationAttributes attributes
= this.getAttributes(annotationMetadata);
//从spring-boot-autoconfigure jar包里面META-INF/spring.factories加载配置类的名称,打开这个文件发现里面包含了springboot框架提供的所有配置类
List<String> configurations
= this.getCandidateConfigurations(
annotationMetadata,
attributes);
//去掉重复项
configurations = this.removeDuplicates(configurations);
configurations = this.sort(
configurations,
autoConfigurationMetadata);
//获取自己配置不需要生成bean的class
Set<String> exclusions = this.getExclusions(
annotationMetadata,
attributes);
//校验被exclude的类是否都是springboot自动化配置里的类,如果存在抛出异常
this.checkExcludedClasses(configurations, exclusions);
//删除被exclude掉的类
configurations.removeAll(exclusions);
//过滤刷选,满足OnClassCondition的类
configurations = this.filter(
configurations,
autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(
configurations,
exclusions);
//返回需要注入的bean的类路径
return StringUtils.toStringArray(configurations);
} catch (IOException var6) {
throw new IllegalStateException(var6);
}
}
}
@ComponentScan
Spring Frameworkを使用したことのある人は、Springには4つの主要な注釈があることを知っています。
- @サービス、
- @リポジトリ、
- @成分、
- @Controllerは
、Beanを定義するために使用されます。@ ComponentScanアノテーションは、これらのアノテーションによって識別されるクラスを自動的にスキャンし、最後にiocコンテナーにBeanを生成するために使用されます。@ComponentScan basePackages、includeFilters、およびexcludeFilters属性を設定することにより、自動スキャンの範囲を動的に決定でき、タイプはスキャンされません。デフォルト:すべてのタイプをスキャンします。スキャンスコープは、@ ComponentScanアノテーションが配置されている構成パッケージとサブパッケージのクラスです。
RestTemplateテンプレートツールクラス
Springは、HTTPベースのクライアントをカプセル化するRestTemplateテンプレートツールクラスを提供し、オブジェクトとjsonのシリアル化と逆シリアル化を実現します。これは非常に便利です。RestTemplateはHTTPクライアントタイプを制限しませんが、それを抽象化します。現在、3つの一般的に使用されるタイプがサポートされています。
- HTTPClient
- OkHTTP
- JDKネイティブURLConnection(デフォルト)
ConsumerApplication:
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
UserController:
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
String url = "http://localhost:9091/user/" + id;
return restTemplate.getForObject(url, User.class);
}
}
ユーレカレジストリ
考え
ユーザーサービスは外部にサービスを提供し、そのアドレスを外部に公開する必要があります。コンシューマー(呼び出し元)は、サービスプロバイダーのアドレスを記録する必要があります。将来アドレスが変更された場合は、時間内に更新する必要があります。サービスが少ない場合、これは問題ではないようですが、今日のますます複雑化するインターネット環境では、プロジェクトは間違いなく数十または数十のマイクロサービスを分割します。現時点で、アドレスを手動で管理していると、開発が困難になるだけでなく、将来のテストとリリースが非常に面倒になります。これは、DevOpsの考え方に反します。
アーキテクチャ図
Eureka:アドレス
プロバイダーを公開するのはサービス登録センター(クラスターの場合もあります)です。起動後、Spring Bootアプリケーションまたはその他の技術的な実装のEurekaに情報(アドレス、提供するサービス)を登録します。 。RESTスタイルのサービスを外の世界に提供する限り。
コンシューマー:Eurekaサービスにサブスクライブすると、Eurekaは対応するサービスのすべてのプロバイダーのアドレスリストをコンシューマーに送信し、定期的に更新します。
ハートビート(更新):プロバイダーは、HTTPを介してEurekaにステータスを定期的に更新します。
ビルド
Eurekaはサービス登録センターであり、サービス登録のみを行い、サービスを提供したり、サービスを利用したりすることはありません。Eurekaを使用してWebプロジェクトを構築することも、SpringBootを使用して構築することもできます。
eurekaレジストリ
サーバ
依存関係を追加する
<!-- Eureka服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
クラスを開始
@EnableEurekaServer //声明当前应用时Eureka服务
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
構成ファイル
# 指定端口号
server.port=10086
# 给服务起个名字
spring.application.name=eureka-sevver
# eureka 服务地址,如果是集群的话;需要指定其它集群eureka地址
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka
# 不注册自己
eureka.client.register-with-eureka=false
# 不拉取服务
eureka.client.fetch-registry=false
クライアント登録
Eurekaクライアントの依存関係をサービス消費プロジェクトconsumer-demoに追加します。ツールクラスDiscoveryClientを使用して、サービス名に基づいて対応するサービスアドレスリストを取得できます。
依存関係を追加する
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
クラスを開始
@SpringBootApplication
@EnableDiscoveryClient // 开启Eureka客户端
public class UserConsumerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerDemoApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
構成ファイル
# 给服务起个名字
spring.application.name=consumer-demo
# eureka服务地址
eureka.client.service-url.defaultZone=http://127.0.0.1:10086/eureka
コードを変更する
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){
// String url = "http://localhost:9091/user/" + id;
// 拉取注册在eureka注册中心的所有叫user-service的服务
List<ServiceInstance> serviceInstances =
discoveryClient.getInstances("user-service");
// 我们只注册了一个,那么只需要获取0号下标的索引即可
ServiceInstance serviceInstance = serviceInstances.get(0);
// 拼接字符串形成一个url地址
String url = "http://" +
serviceInstance.getHost() +
":" +
serviceInstance.getPort() +
"/user/" +
id;
return restTemplate.getForObject(url, User.class);
}
}
高可用性eurekaサーバー
複数のEurekaサーバーも相互にサービスとして登録します。サービスプロバイダーがEurekaサーバークラスター内のノードに登録すると、ノードはサービス情報をクラスター内の各ノードに同期して、データの同期を実現します。したがって、クライアントがEurekaサーバークラスター内のノードにアクセスしても、完全なサービスリスト情報を取得できます。