一篇文章概括Spring Cloud微服务教程

栏目: Java · 发布时间: 7年前

内容简介:现在流行的是基于Spring Cloud的MicroServices的Hearth是Eureka Server。也称为Discovery Server。因为该服务器保存有关您的系统可以在其运行位置,健康状况和其他方面使用的所有微服务的信息。很明显,在生产中,这个服务器需要具有高可用性。使用Spring Cloud,您可以通过将EnableEurekaServer注释添加到Spring Boot应用程序的启动类来创建此服务器。

现在流行的是 Spring Cloud基于NetFlix解决 方案提供的 解决方案 。那么让我们来演示如何使用它。原文来自tomask79,点击标题见原文!

1. 注册中心

基于Spring Cloud的MicroServices的Hearth是Eureka Server。也称为Discovery Server。因为该服务器保存有关您的系统可以在其运行位置,健康状况和其他方面使用的所有微服务的信息。很明显,在生产中,这个服务器需要具有高可用性。使用Spring Cloud,您可以通过将EnableEurekaServer注释添加到Spring Boot应用程序的启动类来创建此服务器。

@SpringBootApplication
@EnableEurekaServer
<b>public</b> <b>class</b> SpringMicroserviceRegistryApplication {

    <b>public</b> <b>static</b> <b>void</b> main(String[] args) {
        SpringApplication.run(SpringMicroserviceRegistryApplication.<b>class</b>, args);
    }
}

只需要这一行代码就可以启动eureka服务器了,默认在 http://localhost:8761 可访问注册中心,可以在application.properties/yaml中配置端口等特定配置:

server.port=9761

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF

在调试环境可以配置关闭一些参数:

  • eureka.client.register-with-eureka和eureka.client.fetch-registr参数设置为false表示注册服务器不向自己注册服务。
  • 对logging.level.com.netflix.eureka和logging.level.com.netflix.discovery的设置OFF,关闭了“没有用于注册服务器的副本节点”的警告信息。

微服务注册到Discovery Server

现在让我们实现我们的微服务。首先,Spring Boot应用程序需要知道在哪里注册您的微服务:

spring.application.name=personsService
eureka.client.serviceUrl.defaultZone=http:<font><i>//localhost:9761/eureka</i></font><font>
</font>

还要注意微服务名为“ personsService ”。现在编码微服务,是一个简单的REST控制器返回一些JSON:

@RestController
<b>public</b> <b>class</b> PersonsController {

    @RequestMapping(<font>"/persons"</font><font>)
    <b>public</b> Persons getPersonById() {
        <b>final</b> Persons persons = <b>new</b> Persons();
        <b>final</b> Person person = <b>new</b> Person();
        person.setName(</font><font>"Tomas"</font><font>);
        person.setSurname(</font><font>"Kloucek"</font><font>);
        person.setDepartment(</font><font>"Programmer"</font><font>);
        persons.getPersons().add(person);

        <b>return</b> persons;
    }
}
</font>

Spring Cloud MicroService的客户端

现在你可以访问 http://localhost:8080/persons ,也可以使用使用RestTemplate 直接访问这个微服务, 但这样做是愚蠢的。更聪明的是让您的客户端通过MicroService id(在我的情况下是personService)首先访问注册服务器,询问Ribbon loadbalancer负载平衡器来获取微服务的URL,然后调用该服务。查看客户端代码:

首先,我们需要让我们的客户端成为发现服务器客户端。因此EnableDiscoveryClient注释。(Spring Boot 2以后可不需要此注释)

@SpringBootApplication
@EnableDiscoveryClient
<b>public</b> <b>class</b> SpringMicroserviceClientApplication {

    <b>public</b> <b>static</b> <b>void</b> main(String[] args) {
        SpringApplication.run(SpringMicroserviceClientApplication.<b>class</b>, args);
    }
}

然后我们需要让Ribbon loadbalancer通过提供服务ID来选择微服务的一个实例。

@Component
<b>public</b> <b>class</b> MicroServiceClient implements CommandLineRunner {

    @Autowired
    <b>private</b> LoadBalancerClient loadBalancer;

    @Override
    <b>public</b> <b>void</b> run(String... arg0) throws Exception {
        <b>final</b> RestTemplate restTemplate = <b>new</b> RestTemplate();

        <b>final</b> ServiceInstance serviceInstance = loadBalancer.choose(<font>"personsService"</font><font>);
        <b>if</b> (serviceInstance != <b>null</b>) {
            System.out.println(</font><font>"Invoking instance at URL: "</font><font>+serviceInstance.getUri());
            System.out.println(
                restTemplate.getForObject(serviceInstance.getUri()+</font><font>"/persons"</font><font>, String.<b>class</b>));
        } <b>else</b> {
            System.out.println(</font><font>"Didn't find any running instance of personsService at DiscoveryServer!"</font><font>);
        }
    }
}
</font>

LoadBalancerClient将在Discovery服务器上选择注册的一个正在运行的微服务实例!(banq注:通常需要通过Feign实现JSON对象转换的方式访问远程微服务)

运行演示

下载 演示

运行发现服务器

  • mvn clean install(在带有pom.xml的spring-microservice-registry目录下)
  • java -jar target / demo-0.0.1-SNAPSHOT.war
  • 访问 http:// localhost:9761

运行MicroService

  • mvn clean install(在带有pom.xml的spring-microservice-service目录下)
  • java -jar target/demo-0.0.1-SNAPSHOT.war
  • 现在重新刷新 http:// localhost:9761 页面,您应该看到MicroService已在发现服务器上注册。

运行客户端

  • mvn clean install(在带有pom.xml的spring-microservice-client目录下)
  • java -jar target/demo-0.0.1-SNAPSHOT.war

2. 在Spring Cloud 微服务中使用断路器Circuit-Breaker

在编写微服务时,如果无法访问特定微服务,需要告诉微服务要执行什么操作。也就是说当被访问的微服务不可用时,有几个选项:

  • 调用另一个备份微服务。
  • 返回一些缓存的结果。
  • 返回不可用的页面...

用于实现此目的的广泛使用的模式是 断路器 模式。在你继续阅读之前,一定要阅读Martin Fowler定义的这个描述。

无论如何,简而言之。断路器的作用是将MicroService调用方法包装在代理监控MicroService调用失败中。如果失败将达到某个阈值,则所有其他调用将以异常结束,或者如果您使用备份计划调用来定义... Spring Cloud具有出色的实现,称为 Hystrix

使用Hystrix断路器

使用之前的personsService这个微服务,使用以下规则向调用者添加容错逻辑:

每20秒(metrics.rollingStats.timeInMilliseconds)从6个请求(收集统计数据circuitBreaker.requestVolumeThreshold),如果所有的人都用崩溃(截至circuitBreaker.errorThresholdPercentage)然后重定向调用到后备逻辑。每隔5秒尝试一次这个微服务是否可用(circuitBreaker.sleepWindowInMilliseconds)。

提到的MicroService调用组件将如下所示:

@Component
<b>public</b> <b>class</b> MicroServiceInvoker {

    @Autowired
    <b>private</b> LoadBalancerClient loadBalancer;

    @HystrixCommand(fallbackMethod = <font>"invokeMicroServiceFallback"</font><font>,
                commandProperties = {
                    @HystrixProperty(name = </font><font>"circuitBreaker.errorThresholdPercentage"</font><font>, value = </font><font>"100"</font><font>),
                    @HystrixProperty(name = </font><font>"metrics.rollingStats.timeInMilliseconds"</font><font>, value = </font><font>"20000"</font><font>),
                    @HystrixProperty(name = </font><font>"circuitBreaker.requestVolumeThreshold"</font><font>, value = </font><font>"6"</font><font>),
                    @HystrixProperty(name = </font><font>"circuitBreaker.sleepWindowInMilliseconds"</font><font>, value = </font><font>"5000"</font><font>)
                }
            )
    <b>public</b> <b>void</b> invokeMicroService() {
        <b>final</b> RestTemplate restTemplate = <b>new</b> RestTemplate();

        <b>final</b> ServiceInstance serviceInstance = loadBalancer.choose(</font><font>"personsService"</font><font>);
        <b>if</b> (serviceInstance != <b>null</b>) {
            System.out.println(</font><font>"Invoking instance at URL: "</font><font>+serviceInstance.getUri());
            System.out.println(</font><font>"Result :"</font><font>+
                    restTemplate.getForObject(serviceInstance.getUri()+</font><font>"/persons"</font><font>,
                            String.<b>class</b>));
        } <b>else</b> {
            System.out.println(</font><font>"Service is down..."</font><font>);
            <b>throw</b> <b>new</b> IllegalStateException(</font><font>"PersonsService is not running!"</font><font>);
        }
    }

    <b>public</b> <b>void</b> invokeMicroServiceFallback() {
        System.out.println(</font><font>"Waiting for circuit-breaker to close again..."</font><font>);
    }
}
</font>

测试断路器

下载 源码

运行发现服务器:

mvn clean install (in the spring-microservice-registry directory with pom.xml)
java -jar target/demo-0.0.1-SNAPSHOT.war

运行微服务

mvn clean install (in the spring-microservice-service directory with pom.xml)
java -jar target/demo-0.0.1-SNAPSHOT.war

在http://localhost:9761确认微服务已经注册。

运行另外一个微服务,它是上面微服务客户端,调用者:

mvn clean install (in the spring-microservice-client directory with pom.xml)
java -jar target/demo-0.0.1-SNAPSHOT.war

启动客户端你会看到:

Invocation number :16
Invoking instance at URL: http:<font><i>//192.168.1.112:8080</i></font><font>
Result :{</font><font>"persons"</font><font>:[{</font><font>"name"</font><font>:</font><font>"Tomas"</font><font>,</font><font>"surname"</font><font>:</font><font>"Kloucek"</font><font>,</font><font>"department"</font><font>:</font><font>"Programmer"</font><font>}]}
Invocation number :17
Invoking instance at URL: http:</font><font><i>//192.168.1.112:8080</i></font><font>
Result :{</font><font>"persons"</font><font>:[{</font><font>"name"</font><font>:</font><font>"Tomas"</font><font>,</font><font>"surname"</font><font>:</font><font>"Kloucek"</font><font>,</font><font>"department"</font><font>:</font><font>"Programmer"</font><font>}]}
Invocation number :18
Invoking instance at URL: http:</font><font><i>//192.168.1.112:8080</i></font><font>
Result :{</font><font>"persons"</font><font>:[{</font><font>"name"</font><font>:</font><font>"Tomas"</font><font>,</font><font>"surname"</font><font>:</font><font>"Kloucek"</font><font>,</font><font>"department"</font><font>:</font><font>"Programmer"</font><font>}]}
Invocation number :19
</font>

关闭personService微服务 20秒, 你会看到输出:

Invocation number :18
Invoking instance at URL: http:<font><i>//192.168.1.112:8080</i></font><font>
Waiting <b>for</b> circuit-breaker to close again...
Invocation number :19
Invoking instance at URL: http:</font><font><i>//192.168.1.112:8080</i></font><font>
Waiting <b>for</b> circuit-breaker to close again...
</font>

一会儿看到输出:

Invocation number :78
Waiting <b>for</b> circuit-breaker to close again...
Invocation number :79
Waiting <b>for</b> circuit-breaker to close again...

每隔5秒改变到:

Invoking instance at URL: http:<font><i>//192.168.1.112:8080</i></font><font>
Waiting <b>for</b> circuit-breaker to close again...
</font>

当Hystrix测试微服务实例是否再次正常运行时,在你运行微服务之后,断路器应该是关闭的,微服务客户端在启动运行时就能发现这个情况...总而言之,断路器有以下状态:

  • OPEN:微服务调用时发生异常,调用回退逻辑
  • CLOSED:没有错误。正确调用MicroService。
  • HALF-OPENED:当circuitBreakerSleepWindowInMilliseconds时间发生时,Hystrix将允许请求调用微服务来测试它是否处于活动状态=半开状态。

3. 使用Netlix Feign作为调用微服务

之前展示了一个微服务客户端如何在 Ribbon的 帮助下使用 RestTemplate 调用另外一个微服务的:

@Component
<b>public</b> <b>class</b> MicroServiceClient implements CommandLineRunner {

    @Autowired
    <b>private</b> LoadBalancerClient loadBalancer;

    @Override
    <b>public</b> <b>void</b> run(String... arg0) throws Exception {
        <b>final</b> RestTemplate restTemplate = <b>new</b> RestTemplate();

        <b>final</b> ServiceInstance serviceInstance = loadBalancer.choose(<font>"personsService"</font><font>);
        <b>if</b> (serviceInstance != <b>null</b>) {
            System.out.println(</font><font>"Invoking instance at URL: "</font><font>+serviceInstance.getUri());
            System.out.println(
                restTemplate.getForObject(serviceInstance.getUri()+</font><font>"/persons"</font><font>, String.<b>class</b>));
        } <b>else</b> {
            System.out.println(</font><font>"Didn't find any running instance of personsService at DiscoveryServer!"</font><font>);
        }
    }
}
</font>

老实说,这里有太多的样板代码,在大型系统中会经常重复。这是引入 Feign 的理由:

Feign为您带来以下好处:

  • 调用代码是在运行时根据注释创建的。
  • 无需使用任何负载平衡器来调用其他微服务。
  • 微服务调用系统更易于维护。

使用Feign的先前代码将如下所示:

远程微服务调用返回的是原始JSON,那么大多数时候你都想要的是Java POJO。因此,让我们创建另一个调用相同MicroService的Feign客户端声明:

@Component
@FeignClient(<font>"personsService"</font><font>)
<b>public</b> <b>interface</b> JacksonMicroServiceFeignClient {
    @RequestMapping(method = RequestMethod.GET, value = </font><font>"/persons"</font><font>)
    ClientPersonsTO invokePersonsMicroService();
}
</font>

只要调用上面这个接口就可以实现远程微服务的调用,比如:

@Autowired
<b>private</b> JacksonMicroServiceFeignClient jacksonMicroServiceFeignClient;
.
.
<b>final</b> ClientPersonsTO clientPersonsTO = jacksonMicroServiceFeignClient.
                        invokePersonsMicroService();

而远程微服务的代码是这个样子:

@RestController
<b>public</b> <b>class</b> PersonsController {

    @RequestMapping(<font>"/persons"</font><font>)
    <b>public</b> Persons getPersonById() {
        <b>final</b> Persons persons = <b>new</b> Persons();
        <b>final</b> Person person = <b>new</b> Person();
        person.setName(</font><font>"Tomas"</font><font>);
        person.setSurname(</font><font>"Kloucek"</font><font>);
        person.setDepartment(</font><font>"Programmer"</font><font>);
        persons.getPersons().add(person);

        <b>return</b> persons;
    }
}
</font>

远程微服务返回的是Persons对象,这个Persons是通过转换成JSON到达你的客户端的,你的Feign客户端将这个JSON字符串又转换为ClientPersonsTO,两者名称可以不同,但是内部数据结构应该相同额。

将Feign与Hystrix结合起来

在具有maven依赖关系的类路径中包含Hystrix:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

当然你也应该包含进Feign等组件,这些配置可以通过Idea等Spring 导航选择相应组件后自动生成pom.xml配置。

​​​​​​​

从现在开始,Feign将用Hystrix封装每个MS微服务呼叫。您可以通过以下设置禁用它:feign.hystrix.enabled = false应用程序属性。您的Feign客户端接口方法也可以返回HystrixCommand以允许调用者使用带有Observable Java的反应模式。那么让我们创建Feign Hystrix客户端:

@Component
@FeignClient(value = <font>"personsService"</font><font>, fallback = MicroServiceHystrixFallback.<b>class</b>)
<b>public</b> <b>interface</b> HystrixMicroServiceFeignClient {
    @RequestMapping(method = RequestMethod.GET, value = </font><font>"/persons"</font><font>)
    ClientPersonsTO getPersonsWithHystrix();
}
</font>

如果断路器打开,我在这里定义了后备也就是快速失败或回退返回。顺便说一句,当返回HystrixCommand时,还不支持fallback 。现在,使用 archaius 配置Feign Hystrix,它使用方法名作为command键,因此application.properties中的配置将是:

server.port=8888
eureka.client.serviceUrl.defaultZone=http:<font><i>//localhost:9761/eureka</i></font><font>
hystrix.command.getPersonsWithHystrix.fallback.enabled=<b>true</b>
hystrix.command.getPersonsWithHystrix.metrics.rollingStats.timeInMilliseconds=35000
hystrix.command.getPersonsWithHystrix.circuitBreaker.sleepWindowInMilliseconds=5000
hystrix.command.getPersonsWithHystrix.circuitBreaker.requestVolumeThreshold=6
hystrix.command.getPersonsWithHystrix.circuitBreaker.errorThresholdPercentage=100
hystrix.command.getPersonsWithHystrix.execution.isolation.strategy=THREAD
</font>

测试

下载 源码

运行Eureka:

mvn clean install (in the spring-microservice-registry directory with pom.xml)
java -jar target/demo-0.0.1-SNAPSHOT.war

运行被调用微服务:

mvn clean install (in the spring-microservice-service directory with pom.xml)
java -jar target/demo-0.0.1-SNAPSHOT.war
verify with http:<font><i>//localhost:9761 that MicroService is registered.</i></font><font>
</font>

运行调用微服务:

mvn clean install (in the spring-microservice-client directory with pom.xml)
java -jar target/demo-0.0.1-SNAPSHOT.war [0-2]

以上所述就是小编给大家介绍的《一篇文章概括Spring Cloud微服务教程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First Rails

Head First Rails

David Griffiths / O'Reilly Media / 2008-12-30 / USD 49.99

Figure its about time that you hop on the Ruby on Rails bandwagon? You've heard that it'll increase your productivity exponentially, and allow you to created full fledged web applications with minimal......一起来看看 《Head First Rails》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具