>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring:Java Web开发技术详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 24320 个阅读者 刷新本主题
 * 贴子主题:  一篇文章概括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面向对象编程-->异常处理
  JavaWeb开发-->开发JavaMail Web应用
  JSP与Hibernate开发-->持久化层的映射类型
  Java网络编程-->客户端协议处理框架
  精通Spring-->通过Axios访问服务器
  Vue3开发-->组合(Composition)API
  Redis为什么单线程能够支持高并发
  SpringCloud服务间内部调用原理
  从零开始手写 spring ioc 框架,深入学习 spring 源码
  git 仓库常用指令
  微服务架构集大成者—Spring Cloud简明教程
  微服务架构模型
  微服务架构模型
  9种设计模式在Spring中的运用,一定要非常熟练!
  Spring Data JPA详解
  解析配置文件 redis.conf、Redis持久化RDB、Redis的主从复制
  Spring Cloud与Dubbo的完美融合之手「Spring Cloud Alibaba
  如何实现Git服务间同步
  Spring Boot集成EHCache实现缓存机制
  网红框架SpringBoot2.x之定制参数浅析
  再谈响应式流(结合制奶厂业务的案例)
  更多...
 IPIP: 已设置保密
树形列表:   
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


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