Spring Framework 5.0的响应式微服务

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
简介: 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/56289457 Spring Framework 5.0的响应式微服务作者:chszs,未经博主允许不得转载。
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/56289457

Spring Framework 5.0的响应式微服务

作者:chszs,未经博主允许不得转载。经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs

Spring团队已经宣布从5.0版本开始支持响应式编程模型。新的Spring 5.0版本可能会在今年3月发布。幸运的是,包含这些特性的里程碑版本和快照版本(非稳定版)现在可以从Spring存储库获得。另外还有一个新的Spring Web Reactive项目,支持响应式的@Controller注解和一个新的WebClient的客户端响应式。下面,可以进一步看看Spring团队提出的解决方案。

遵循这个文档,见:
http://docs.spring.io/spring-framework/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/web-reactive.html

Spring框架在内部使用Reactor实现了对响应式的支持。Reactor是一个Reactive Streams的实现,它进一步扩展了基本的Reactive Streams Publisher以及Flux和Mono composable API,对数据序列0…N和0…1提供了声明式的操作。在服务器端,Spring支持基于注释和函数式编程模型。注释模型使用了@Controller注解和其他同时也支持Spring MVC的注解。对于同步服务,响应式控制器与标准REST控制器是非常相似的,下面说明如何怎样使用注释模型和MongoDB的响应式模块来开发一个简单的响应式微服务。

在例子中,使用了Spring Boot 2.0.0快照版和Spring Web Reactive 0.1.0版。依赖配置pom.xml的主要片段和单个微服务的内容如下。在微服务中,使用Netty来代替了默认的Tomcat服务器。

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<dependencyManagement>
<dependencies>
    <dependency>
      <groupId>org.springframework.boot.experimental</groupId>
      <artifactId>spring-boot-dependencies-web-reactive</artifactId>
      <version>0.1.0.BUILD-SNAPSHOT</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot.experimental</groupId>
    <artifactId>spring-boot-starter-web-reactive</artifactId>
    <exclusions>
      <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>io.projectreactor.ipc</groupId>
    <artifactId>reactor-netty</artifactId>
  </dependency>
  <dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
  </dependency>
  <dependency>
    <groupId>pl.piomin.services</groupId>
    <artifactId>common</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>io.projectreactor.addons</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>
AI 代码解读

有两个微服务:帐户服务和客户服务。每个微服务都有自己的MongoDB数据库,且对外暴露简单的响应式API,用于搜索和保存数据。另外,客户服务与帐户服务可以相互通信,以获取所有的客户帐户,并通过客户服务API方法返回。下面是帐户控制器代码:

@RestController
public class AccountController {
  @Autowired
  private AccountRepository repository;
  @GetMapping(value = "/account/customer/{customer}")
  public Flux<Account> findByCustomer(@PathVariable("customer") Integer customerId) {
    return repository.findByCustomerId(customerId)
    .map(a -> new Account(a.getId(), a.getCustomerId(), a.getNumber(), a.getAmount()));
  }
  @GetMapping(value = "/account")
  public Flux<Account> findAll() {
  return repository.findAll().map(a -> new Account(a.getId(), a.getCustomerId(), a.getNumber(), a.getAmount()));
  }
  @GetMapping(value = "/account/{id}")
  public Mono<Account> findById(@PathVariable("id") Integer id) {
    return repository.findById(id)
    .map(a -> new Account(a.getId(), a.getCustomerId(), a.getNumber(), a.getAmount()));
  }
  @PostMapping("/person")
  public Mono<Account> create(@RequestBody Publisher<Account> accountStream) {
    return repository
    .save(Mono.from(accountStream)
    .map(a -> new pl.piomin.services.account.model.Account(a.getNumber(), a.getCustomerId(),
    a.getAmount())))
    .map(a -> new Account(a.getId(), a.getCustomerId(), a.getNumber(), a.getAmount()));
  }
}
AI 代码解读

在所有API方法中,还执行common模块从帐户实体(MongoDB @Document注解的)到帐户DTO的映射。下面是帐户存储库类。它使用ReactiveMongoTemplate与Mongo集合进行交互。

@Repository
public class AccountRepository {
  @Autowired
  private ReactiveMongoTemplate template;
  public Mono<Account> findById(Integer id) {
  return template.findById(id, Account.class);
  }
  public Flux<Account> findAll() {
  return template.findAll(Account.class);
  }
  public Flux<Account> findByCustomerId(String customerId) {
  return template.find(query(where("customerId").is(customerId)), Account.class);
  }
  public Mono<Account> save(Mono<Account> account) {
  return template.insert(account);
  }
}
AI 代码解读

在Spring Boot的main或@Configuration类中,应该为MongoDB声明Spring Bean以及连接设置。

@SpringBootApplication
public class Application {
  public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
  }
  public @Bean MongoClient mongoClient() {
  return MongoClients.create("mongodb://192.168.99.100");
  }
  public @Bean ReactiveMongoTemplate reactiveMongoTemplate() {
  return new ReactiveMongoTemplate(mongoClient(), "account");
  }
}
AI 代码解读

使用docker MongoDB容器来处理这个示例。

docker run -d --name mongo -p 27017:27017 mongo
AI 代码解读

在客户服务中,从帐户服务调用端点的/account/customer/{customer}。在主类中声明为@Bean WebClient。

@Autowired
private WebClient webClient;
@GetMapping(value = "/customer/accounts/{pesel}")
public Mono<Customer> findByPeselWithAccounts(@PathVariable("pesel") String pesel) {
return repository.findByPesel(pesel).flatMap(customer -> webClient.get().uri("/account/customer/{customer}", customer.getId()).accept(MediaType.APPLICATION_JSON)
.exchange().flatMap(response -> response.bodyToFlux(Account.class))).collectList().map(l -> {return new Customer(pesel, l);});
}
AI 代码解读

可以使用Web浏览器或REST客户端来测试GET调用。而用POST,则没有那么简单。下面有两个简单的测试用例,用于添加新客户和获得客户的帐户信息。要测试getCustomerAccounts,需要先在端口2222上运行帐户服务。

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CustomerTest {
  private static final Logger logger = Logger.getLogger("CustomerTest");
  private WebClient webClient;
  @LocalServerPort
  private int port;
  @Before
  public void setup() {
  this.webClient = WebClient.create("http://localhost:" + this.port);
  }
  @Test
  public void getCustomerAccounts() {
    Customer customer = this.webClient.get().uri("/customer/accounts/234543647565")
    .accept(MediaType.APPLICATION_JSON).exchange().then(response -> response.bodyToMono(Customer.class))
    .block();
    logger.info("Customer: " + customer);
  }
  @Test
  public void addCustomer() {
    Customer customer = new Customer(null, "Adam", "Kowalski", "123456787654");
    customer = webClient.post().uri("/customer").accept(MediaType.APPLICATION_JSON)
    .exchange(BodyInserters.fromObject(customer)).then(response -> response.bodyToMono(Customer.class))
    .block();
    logger.info("Customer: " + customer);
  }
}
AI 代码解读

结论

Spring框架开始支持响应式编程非常不错,但现在它还处于早期阶段,也没法与Spring Cloud等项目一起使用。希望在不久的将来,类似服务发现和负载平衡的功能也可用于与Spring响应式微服务相集成。Spring还有一个Spring Cloud Stream项目,支持响应式模型。以后再看吧!

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
chszs
+关注
目录
打赏
0
0
0
0
1098
分享
相关文章
|
3月前
|
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
211 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
113 2
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
344 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
62 7
微服务架构设计与实践:用Spring Cloud实现抖音的推荐系统
本文基于Spring Cloud实现了一个简化的抖音推荐系统,涵盖用户行为管理、视频资源管理、个性化推荐和实时数据处理四大核心功能。通过Eureka进行服务注册与发现,使用Feign实现服务间调用,并借助Redis缓存用户画像,Kafka传递用户行为数据。文章详细介绍了项目搭建、服务创建及配置过程,包括用户服务、视频服务、推荐服务和数据处理服务的开发步骤。最后,通过业务测试验证了系统的功能,并引入Resilience4j实现服务降级,确保系统在部分服务故障时仍能正常运行。此示例旨在帮助读者理解微服务架构的设计思路与实践方法。
124 17
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
108 7
|
3月前
|
Spring Cloud Alibaba:一站式微服务解决方案
Spring Cloud Alibaba(简称SCA) 是一个基于 Spring Cloud 构建的开源微服务框架,专为解决分布式系统中的服务治理、配置管理、服务发现、消息总线等问题而设计。
599 13
Spring Cloud Alibaba:一站式微服务解决方案
|
3月前
|
为何内存不够用?微服务改造启动多个Spring Boot的陷阱与解决方案
本文记录并复盘了生产环境中Spring Boot应用内存占用过高的问题及解决过程。系统上线初期运行正常,但随着业务量上升,多个Spring Boot应用共占用了64G内存中的大部分,导致应用假死。通过jps和jmap工具排查发现,原因是运维人员未设置JVM参数,导致默认配置下每个应用占用近12G内存。最终通过调整JVM参数、优化堆内存大小等措施解决了问题。建议在生产环境中合理设置JVM参数,避免资源浪费和性能问题。
152 3
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
220 5
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等