この記事では、春雲とは何ですか? Spring Cloud の使用方法については、参考にしていただければ幸いです。
1. Spring Cloud とは何ですか?
Spring は、開発者が分散システムで共通コンポーネント (構成管理、サービス検出、サーキット ブレーカー、インテリジェント ルーティング、マイクロ エージェント、コントロールなど) を迅速に構築できるようにする一連のツールを提供します。バス、ワンタイム トークン、グローバル ロック、マスター ノードの選択、分散セッション、クラスター ステータス)。分散環境でさまざまなシステムを連携し、さまざまなサービスのテンプレート構成を提供します。 Spring Cloud を使用すると、開発者はこれらのテンプレートを実装し、ラップトップからデータセンター、クラウド プラットフォームに至るまで、あらゆる分散環境で適切に動作するアプリケーションを構築できます。
Spring Cloud は Spring Boot をベースにしており、Spring Boot で作成されたさまざまなマイクロサービス アプリケーションの管理に最適です。分散環境で各 Spring Boot マイクロサービスを管理するには、サービス登録の問題が発生する必要があります。それでは、サービスの登録から始めましょう。これは登録であるため、Spring Cloud 管理下の各 Spring Boot アプリケーションが登録する必要があるクライアントとなるため、登録センターを管理するサーバーが必要です。
Spring Cloud は erureka サーバーを使用しており、構成ファイルにアクセスする必要があるすべてのアプリケーションは erureka クライアントとして登録されます。 Eureka は高可用性コンポーネントであり、各インスタンスが登録された後、ハートビートを登録センターに送信する必要があり、サーバーを指定する必要があります。 。
1. Eureka サーバーの作成
最初に Spring Boot プロジェクトを作成します
pom ファイル
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>me.cn</groupId> <artifactId>test</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>test</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>10</java.version> <spring-cloud.version>Finchley.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </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>
アノテーション @EnableEurekaServer の追加が必要ですspringboot プロジェクトのスタートアップ クラス
@EnableEurekaServer @SpringBootApplication public class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } }
eureka サーバーの構成ファイル application.yml
server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
eureka サーバーを起動し、http://localhost:8761 にアクセスします。インターフェイスは次のとおりです。 、「利用可能なインスタンスがありません」は、クライアント登録がないことを意味します
2. Eureka Client を作成します
pom ファイル
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.chry</groupId> <artifactId>test1</artifactId> <version>0.0.1-SNAPSHOT</version> <name>test1</name> <packaging>jar</packaging> <description>Demo Spring Boot Client</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</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>Dalston.RC1</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> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
@EnableEurekaClient アノテーションを使用して、これがクライアントであることを確認します
@SpringBootApplication @EnableEurekaClient @RestController public class Test1Application { public static void main(String[] args) { SpringApplication.run(Test1Application.class, args); } @Value("${server.port}") String port; @RequestMapping("/") public String home() { return "hello world from port " + port; } }
yml ファイル構成
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8762 spring: application: name: service-helloworld
最後にクライアントを起動すると、サーバー ポートでクライアントが正常に登録されたことがわかります
##2. 構成管理
Spring Cloud の解決策は、これらの構成ファイルを Spring Cloud のデフォルト構成で使用することです。すべての Web サービスは、GIT からこれらの構成ファイルを取得します。 GIT サーバーと特定の Web サーバーの間でストレージを共有する必要がないため、ネットワークにアクセスできる限り、Web サービスを構成情報の保存場所から切り離すことができます。2.1 構成サーバーの作成
pom ファイルにより新しい依存関係が追加されます<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency>
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8888 spring: cloud: config: server: git: uri: https://gitee.com/ning9/CRUD.git searchPaths: spring-cloud/helloworldConfig application: name: config-server
config クライアントを作成します ##スタートアップ ファイル
@SpringBootApplication @RestController public class ConfigClientApplication { public static void main(String[] args) { SpringApplication.run(ConfigClientApplication.class, args); } @Value("${hello}") String hello; @RequestMapping(value = "/hello") public String hello(){ return hello; } }
yml ファイル
spring: application: name: config-client cloud: config: label: master profile: dev uri: http://localhost:8888/ server: port: 8881
config-client アプリケーションを起動すると、http://locahost/8881/hello にアクセスできるようになります。 hello の特定の内容は直接構成されず、特定の構成ファイルはすべて Spring Cloud Framework によって構成サーバーに送信されます。
3. 自動更新を構成するまず、pom.xml に次の依存関係を追加します。
spring-boot-starter-actuator は、/refresh
関数を含む、プログラムの実行状態を監視できる一連の監視関数です。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;"><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency></pre><div class="contentsignin">ログイン後にコピー</div></div>
次に、更新メカニズムを有効にするには、変数をロードするクラスに
をロードする必要があります。他のコードは変更せずにそのままにして、/ を実行します。クライアント上のrefresh
このクラスの下の変数値は、構成クライアントを通じてGITから取得した構成を含めて更新されます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">@SpringBootApplication
@RestController
@RefreshScope
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
@Value("${hello}")
String hello;
@RequestMapping(value = "/hello")
public String hello(){
return hello;
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
ただし、この方法では、更新されたデータを確認するためにメソッドを手動で再実行する必要があります
4. 分散環境での構成サービスの自動検出
config-server をサービス センターに登録hello world アプリケーションを eureka サービス センターに登録します。設定方法は以前と同じです
設定ファイルを変更し、config-server の URL ハードコーディング メカニズムを、サービス センターを介した名前に基づく自動検出メカニズムに変更します。
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/spring: application: name: config-client cloud: config: label: master profile: dev discovery: enabled: true service-id: config-server management: security: enabled: falseserver: port: 8881
我们注释掉了硬编码的config-server的URL配置, 取而代之的是服务注册中心的地址http://localhost:8761/eureka/以及配置服务的名字“config-server”, 同时打开自动发现机制discovery.enable = true. 我们在运行一下hello world应用, 可以发现, GIT里面的内容依然可以访问。此时我们的hello world应用已经完全不知道配置服务的地址,也不知道配置的内容, 所有这些都通过服务注册中心自动发现。
五、客户端的负载均衡
Spring Cloud用Ribbon来实现两个Hello World服务的负载均衡
5.1创建ribbon服务
添加pom依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
创建启动类ServiceRibbonApplication
@SpringBootApplication @EnableDiscoveryClient public class ServiceRibbonApplication { public static void main(String[] args) { SpringApplication.run(ServiceRibbonApplication.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
@EnableDiscoveryClient向服务中心注册,并且注册了一个叫restTemplate的bean。
@ LoadBalanced注册表明,这个restRemplate是需要做负载均衡的。
创建获取一个获取Hello内容的service类
@Service public class HelloService { @Autowired RestTemplate restTemplate; public String getHelloContent() { return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class); } }
这里关键代码就是, restTemplate.getForObject方法会通过ribbon负载均衡机制, 自动选择一个Hello word服务,
这里的URL是“http://SERVICE-HELLOWORLD/",其中的SERVICE-HELLOWORLD是Hello world服务的名字,而注册到服务中心的有两个SERVICE-HELLOWORLD。 所以,这个调用本质是ribbon-service作为客户端根据负载均衡算法自主选择了一个作为服务端的SERVICE-HELLOWORLD服务。然后再访问选中的SERVICE-HELLOWORLD来执行真正的Hello world调用。
六、用声明式REST客户端Feign调用远端http服务
添加新的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
创建启动类,需要加上@EnableFeignClients注解以使用Feign, 使用@EnableDiscoveryClient开启服务自动发现
添加配置文件application.yml, 使用端口8902, 名字定义为service-feign, 并注册到eureka服务中心
定义Feign:一个用@FeignClient注解的接口类
@FeignClient
用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired
注入; 该接口通过value定义了需要调用的SERVICE-HELLOWORLD服务(通过服务中心自动发现机制会定位具体URL); @RequestMapping定义了Feign需要访问的SERVICE-HELLOWORLD服务的URL(本例中为根“/”)
@FeignClient(value = "SERVICE-HELLOWORLD") public interface HelloWorldService { @RequestMapping(value = "/",method = RequestMethod.GET) String sayHello(); }
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient
注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate
对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里
编写一个Controller。
注入之前通过@FeignClient定义生成的bean,
sayHello()映射到http://localhost:8902/hello, 在这里,我修改了Hello World服务的映射,将根“/”, 修改成了“/hello”。
@RestController public class WebController { @Autowired HelloWorldService helloWorldFeignService; @RequestMapping(value = "/hello",method = RequestMethod.GET) public String sayHello(){ return helloWorldFeignService.sayHello(); } }
七、断路器
7.1在Ribbon应用中使用断路器
先添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
在Spring Boot启动类上添加@EnableCircuitBreaker注解
用@HystrixCommand注解标注访问服务的方法
@Service public class HelloService { @Autowired RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "serviceFailure") public String getHelloContent() { return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class); } public String serviceFailure() { return "hello world service is not available !"; } }
@HystrixCommand注解定义了一个断路器,它封装了getHelloContant()方法, 当它访问的SERVICE-HELLOWORLD失败达到阀值后,将不会再调用SERVICE-HELLOWORLD, 取而代之的是返回由fallbackMethod定义的方法serviceFailure()。@HystrixCommand注解定义的fallbackMethod方法,需要特别注意的有两点:
第一, fallbackMethod的返回值和参数类型需要和被@HystrixCommand注解的方法完全一致。否则会在运行时抛出异常。比如本例中,serviceFailure()的返回值和getHelloContant()方法的返回值都是String。
第二, 当底层服务失败后,fallbackMethod替换的不是整个被@HystrixCommand注解的方法(本例中的getHelloContant), 替换的只是通过restTemplate去访问的具体服务。可以从中的system输出看到, 即使失败,控制台输出里面依然会有“call SERVICE-HELLOWORLD”。
7.2在Feign应用中使用断路器
用@FeignClient注解添加fallback类, 该类必须实现@FeignClient修饰的接口。
@FeignClient(name = "SERVICE-HELLOWORLD", fallback = HelloWorldServiceFailure.class) public interface HelloWorldService { @RequestMapping(value = "/", method = RequestMethod.GET) public String sayHello(); }
创建HelloWorldServiceFailure类, 必须实现被@FeignClient修饰的HelloWorldService接口。注意添加@Component或者@Service注解,在Spring容器中生成一个Bean
@Component public class HelloWorldServiceFailure implements HelloWorldService { @Override public String sayHello() { System.out.println("hello world service is not available !"); return "hello world service is not available !"; } }
在application.yml中添加如下配置:
feign: hystrix: enabled: true
八、路由网管zuul
创建新的工程添加新的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency>
创建启动类: 使用@EnableZuulProxy注解
@EnableZuulProxy @EnableEurekaClient @SpringBootApplication public class ServiceZuulApplication { public static void main(String[] args) { SpringApplication.run(ServiceZuulApplication.class, args); } }
编写zuul服务配置:
简单配置两个路由, 一个路由到ribbon,一个路由到feign; 由于都注册到eureka服务中心,所以都用通过serviceId来发现服务具体地址, path是路由的地址映射关系
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8904 spring: application: name: service-zuul zuul: routes: ribbo: path: /api-ribbon/** serviceId: service-ribbon feign: path: /api-feign/** serviceId: service-feign
这时启动zuul服务, 然后访问http://localhost:8904/api-ribbon可直接路由到http://localhost:8901/.
http://localhost:8904/api-feign/hello可路由到http://localhost:8902/hello
zuul还提供了过滤功能, 只要实现接口ZuulFilter即可对请求先进行筛选和过滤之后再路由到具体服务。
以上が春雲って何? Spring Cloudの使い方の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。