>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring:Java Web开发技术详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 24150 个阅读者 刷新本主题
 * 贴子主题:  一篇文章概括Spring Cloud微服务教程 回复文章 点赞(0)  收藏  
作者:日月光华    发表时间:2020-04-24 02:13:20     消息  查看  搜索  好友  邮件  复制  引用

现在流行的是Spring Cloud基于NetFlix解决方案提供的解决方案。那么让我们来演示如何使用它。

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

    public static void main(String args) {
        SpringApplication.run(SpringMicroserviceRegistryApplication.class, 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://localhost:9761/eureka

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


@RestController
public class PersonsController {

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

        return persons;
    }
}

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

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


@SpringBootApplication
@EnableDiscoveryClient
public class SpringMicroserviceClientApplication {

    public static void main(String args) {
        SpringApplication.run(SpringMicroserviceClientApplication.class, args);
    }
}

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


@Component
public class MicroServiceClient implements CommandLineRunner {

    @Autowired
    private LoadBalancerClient loadBalancer;

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

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

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
public class MicroServiceInvoker {

    @Autowired
    private LoadBalancerClient loadBalancer;

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

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

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

运行发现服务器:

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://192.168.1.112:8080
Result :{"persons":[{"name":"Tomas","surname":"Kloucek","department":"Programmer"}]}
Invocation number :17
Invoking instance at URL: http://192.168.1.112:8080
Result :{"persons":[{"name":"Tomas","surname":"Kloucek","department":"Programmer"}]}
Invocation number :18
Invoking instance at URL: http://192.168.1.112:8080
Result :{"persons":[{"name":"Tomas","surname":"Kloucek","department":"Programmer"}]}
Invocation number :19

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


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

一会儿看到输出:


Invocation number :78
Waiting for circuit-breaker to close again...
Invocation number :79
Waiting for circuit-breaker to close again...

每隔5秒改变到:


Invoking instance at URL: http://192.168.1.112:8080
Waiting for circuit-breaker to close again...

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

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

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


@Component
public class MicroServiceClient implements CommandLineRunner {

    @Autowired
    private LoadBalancerClient loadBalancer;

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

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

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

调用代码是在运行时根据注释创建的。
无需使用任何负载平衡器来调用其他微服务。
微服务调用系统更易于维护。
使用Feign的先前代码将如下所示:
远程微服务调用返回的是原始JSON,那么大多数时候你都想要的是Java POJO。因此,让我们创建另一个调用相同MicroService的Feign客户端声明:


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

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


@Autowired
private JacksonMicroServiceFeignClient jacksonMicroServiceFeignClient;
.
.
final ClientPersonsTO clientPersonsTO = jacksonMicroServiceFeignClient.
                        invokePersonsMicroService();

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


@RestController
public class PersonsController {

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

        return persons;
    }
}

远程微服务返回的是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 = "personsService", fallback = MicroServiceHystrixFallback.class)
public interface HystrixMicroServiceFeignClient {
    @RequestMapping(method = RequestMethod.GET, value = "/persons")
    ClientPersonsTO getPersonsWithHystrix();
}

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


server.port=8888
eureka.client.serviceUrl.defaultZone=http://localhost:9761/eureka
hystrix.command.getPersonsWithHystrix.fallback.enabled=true
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

运行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://localhost:9761 that MicroService is registered.

运行调用微服务:


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

程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->Swing组件(下)
  JavaWeb开发-->开发JavaMail Web应用
  JSP与Hibernate开发-->第一个helloapp应用
  Java网络编程-->基于MVC和RMI的分布式应用
  精通Spring-->Vue CLI脚手架工具
  Vue3开发-->绑定CSS样式
  一篇文章让你彻底了解什么叫Netty!
  SpringCloud服务间内部调用原理
  git 仓库常用指令
  新书《精通Spring:Java Web开发技术详解》出版!!!
  @Configuration注解的用法
  SpringMVC 中 @ControllerAdvice 注解的三种使用场景!
  Spring MVC中Controller的用法
  微服务拆分实践
  SpringCloud Gateway-整体流程
  RabbitMQ的用途、原理以及配置
  阿里面试官问我:如何用Redis设计秒杀系统?我的回答让他比起...
  vue项目编译75%时很慢的解决办法
  一份Spring Boot核心知识清单
  springmvc+ajax异步上传图片
  RESTful 架构详解
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。