为了账号安全,请及时绑定邮箱和手机立即绑定

基于 Spring Cloud 的微服务落地

标签:
Spring Cloud

微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务。但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需要微服务框架的支持。

在Java生态圈,目前使用较多的微服务框架就是集成了包括Netfilix OSS以及Spring的Spring Cloud。它包括:

Spring Cloud Config:配置管理工具,支持使用Git存储配置内容,可以实现应用配置的外部化存储,支持客户端配置信息刷新、加密/解密配置内容等。

Spring Cloud Netflix:对Netflix OSS进行了整合。其中又包括:

Eureka:服务治理组件,包含服务注册中心、服务注册与发现。

Hystrix:容器管理组件,实现断路器模式,倘若依赖的服务出现延迟或故障,则提供强大的容错功能。

Ribbon:客户端负载均衡的服务调用组件。

Feign:基于Ribbon和Hystrix的声明式服务调用组件。

Zuul:网关组件,提供智能路由、访问过滤等功能。

Archaius:外部化配置组件。

Spring Cloud Bus:事件、消息总线。

Spring Cloud Cluster:针对ZooKeeper、Redis、Hazelcast、Consul的选举算法和通用状态模式的实现。

Spring Cloud Cloudfoundry:与Pivotal Cloudfoundry的整合支持。

Spring Cloud Consul:服务发现与配置管理工具。

Spring Cloud Stream:通过Redis、Rabbit或者Kafka实现的消息驱动的微服务。

Spirng Cloud AWS:简化和整合Amazon Web Service。

Spring Cloud Security:安全工具包,提供Zuul代理中对OAuth2客户端请求的中继器。

Spring Cloud Sleuth:Spring Cloud应用的分布式跟踪实现,可以整合Zipkin。

Spring Cloud ZooKeeper:基于ZooKeeper的服务发现与配置管理组件。

Spring Cloud Starters:Spring Cloud的基础组件,是基于Spring Boot风格项目的基础依赖模块。

Spring Cloud CLI:用于在Groovy中快速创建Spring Cloud应用的Spring Boot CLI插件。

服务治理

当一个系统的微服务数量越来越多的时候,我们就需要对服务进行治理,提供统一的服务注册中心,然后在其框架下提供发现服务的功能。这样就避免了对多个微服务的配置,以及微服务之间以及与客户端之间的耦合。

Spring Cloud Eureka是对Netflix Eureka的包装,用以实现服务注册与发现。Eureka服务端即服务注册中心,支持高可用配置。它依托于强一致性提供良好的服务实例可用性,并支持集群模式部署。Eureka客户端则负责处理服务的注册与发现。客户端服务通过annotation与参数配置的方式,嵌入在客户端应用程序代码中。在运行应用程序时,Eureka客户端向注册中心注册自身提供的服务,并周期性地发送心跳更新它的服务租约。

搭建服务注册中心

服务注册中心是一个独立部署的服务(你可以认为它也是一个微服务),所以需要单独为它创建一个项目,并在pom.xml中添加Eureka的依赖:


org.springframework.cloud

spring-cloud-starter-eureka-server

创建Spring Boot Application:

@EnableEurekaServer

@SpringBootApplication

publicclassApplication{

publicstaticvoidmain(String[] args){

newSpringApplicationBuilder(Application.class).web(true).run(args);

   }

}

注册服务提供者

要让自己编写的微服务能够注册到Eureka服务器中,需要在服务的Spring Boot Application中添加@EnableDiscoveryClient注解,如此才能让Eureka服务器发现该服务。当然,pom.xml文件中也需要添加相关依赖:


org.springframework.cloud

spring-cloud-starter-eureka

同时,我们还需要为服务命名,并指定地址。这些信息都可以在application.properties配置文件中配置:

spring.application.name=demo-service

eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

说明:Spring更推荐使用yml文件来维护系统的配置,yml文件可以体现出配置节的层次关系,表现力比单纯的key-value形式更好。如果结合使用后面讲到的Spring Cloud Config,则客户端的配置文件必须命名为bootstrap.properties或者bootstrap.yml。与上述配置相同的yml文件配置为:

spring:

 application:

   name:demo-service

eureka:

 client:

   serviceUrl:

     defaultZone:http://localhost:1111/eureka/

服务发现与消费

在微服务架构下,许多微服务可能会扮演双重身份。一方面它是服务的提供者,另一方面它又可能是服务的消费者。注册在Eureka Server中的微服务可能会被别的服务消费。此时,就相当于在服务中创建另一个服务的客户端,并通过RestTemplate发起对服务的调用。为了更好地提高性能,可以在服务的客户端引入Ribbon,作为客户端负载均衡。

现在假定我们要为demo-service创建一个服务消费者demo-consumer。该消费者自身也是一个Spring Boot微服务,同时也能够被Eureka服务器注册。这时,就需要在该服务的pom.xml中添加eureka与ribbon的依赖:


org.springframework.cloud

spring-cloud-starter-eureka


org.springframework.cloud

spring-cloud-starter-ribbon

然后在主应用类ConosumerApplication中注入RestTemplate,并引入@LoadBalanced注解开启客户端负载均衡:

@EnableDiscoveryClient

@SpringBootApplication

publicclassConsumerApplication{

@Bean

@LoadBalanced

RestTemplaterestTemplate(){

returnnewRestTemplate();

   }

publicstaticvoidmain(String[] args){

       SpringApplication.run(ConsumerApplication.class, args)

   }

}

假设消费demo-service的客户端代码写在demo-consumer服务的其中一个Controller中:

@RestController

publicclassConsumerController{

@Autowired

   RestTemplate restTemplate;

@RequestMapping(value ="/demo-consumer", method = RequestMethod.Get)

publicStringhelloConsumer(){

returnrestTemplate.getForEntity("http://demo-service/demo", String.class).getBody();

   }

}

通过RestTemplate就可以发起对demo-service的消费调用。

声明式服务调用

通过Ribbon和Hystrix可以实现对微服务的调用以及容错保护,但Spring Cloud还提供了另一种更简单的声明式服务调用方式,即Spring Cloud Feign。Feign实际上就是对Ribbon与Hystrix的进一步封装。通过Feign,我们只需创建一个接口并用annotation的方式配置,就可以完成对服务供应方的接口(REST API)绑定。

假设我们有三个服务:

Notification Service

Account Service

Statistics Service

服务之间的依赖关系如下图所示:

webp

要使用Feign来完成声明式的服务调用,需要在作为调用者的服务中创建Client。Client通过Eureka Server调用注册的对应服务,这样可以解除服务之间的耦合。结构如下图所示:

webp

为了使用Feign,需要对应微服务的pom.xml文件中添加如下依赖:


org.springframework.cloud

spring-cloud-starter-feign

同时,还需要在被消费的微服务Application中添加@EnableFeignClients注解。例如在Statistics服务的应用程序类中:

@SpringBootApplication

@EnableDiscoveryClient

@EnableFeignClients

publicclassStatisticsApplication{

publicstaticvoidmain(String[] args){

       SpringApplication.run(StatisticsApplication.class, args);

   }

}

由于Account服务需要调用Statistics服务,因此需要在Account服务项目中增加对应的client接口:

@FeignClient(name ="statistics-service")

publicinterfaceStatisticsServiceClient{

@RequestMapping(method = RequestMethod.PUT, value ="/statistics/{accountName}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)

voidupdateStatistics(@PathVariable("accountName")String accountName, Account account);

}

StatisticsServiceClient接口的updateStatistics()方法会调用URI为/statistics/{accountName}的REST服务,且HTTP动词为put。这个服务其实对应就是Statistics Service中StatisticsController类中的saveStatistics()方法:

@RestController

publicclassStatisticsController{

@Autowired

privateStatisticsService statisticsService;

@RequestMapping(value ="/{accountName}", method = RequestMethod.PUT)

publicvoidsaveStatistics(@PathVariable String accountName, @Valid @RequestBody Account account){

       statisticsService.save(accountName, account);

   }

}

在Account服务中,如果要调用Statistics服务,都应该通过StatisticsServiceClient接口进行调用。例如,Account服务中的AccountServiceImpl要调用updateStatistics()方法,就可以在该类的实现中通过@autowired注入StatisticsServiceClient接口:

@Service

publicclassAccountServiceImplimplementsAccountService{

@Autowired

privateStatisticsServiceClient statisticsClient;

@Autowired

privateAccountRepository repository;

@Override

publicvoidsaveChanges(String name, Account update){

//...

       statisticsClient.updateStatistics(name, account);

   }

}

Notification服务对Account服务的调用如法炮制。

服务容错保护

在微服务架构中,微服务之间可能存在依赖关系,例如Notification Service会调用Account Service,Account Service调用Statistics Service。真实产品中,微服务之间的调用会更加寻常。倘若上游服务出现了故障,就可能会因为依赖关系而导致故障的蔓延,最终导致整个系统的瘫痪。

Spring Cloud Hystrix通过实现断路器(Circuit Breaker)模式以及线程隔离等功能,实现服务的容错保护。

仍然参考前面的例子。现在系统的微服务包括:

上游服务:demo-service

下游服务:demo-consumer

Eureka服务器:eureka-server

假设上游服务可能会出现故障,为保证系统的健壮性,需要在下游服务中加入容错包含功能。首先需要在demo-consumer服务中添加对hystrix的依赖:


org.springframework.cloud

spring-cloud-starter-hystrix

然后在demo-consumer的应用程序类中加入@EnableCircuitBreaker开启断路器功能:

@EnableCircuitBreaker

@EnableDiscoveryClient

@SpringBootApplication

publicclassConsumerApplication{

@Bean

@LoadBalanced

RestTemplaterestTemplate(){

returnnewRestTemplate();

   }

publicstaticvoidmain(String[] args){

       SpringApplication.run(ConsumerApplication.class, args)

   }

}



作者:java菜
链接:https://www.jianshu.com/p/97c9111c8b0a


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消