Spring Cloud Finchley版-02-构建分布式应用

2024-05-13 09:58

本文主要是介绍Spring Cloud Finchley版-02-构建分布式应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

服务消费者 & 提供者

本书使用服务提供者与服务消费者来描述微服务之间的调用关系。下表解释了服务提供者与服务消费者。
表-服务提供者与服务消费者

[td]

名词
定义
服务提供者服务的被调用方(即:为其他服务提供服务的服务)
服务消费者服务的调用方(即:依赖其他服务的服务)
以电影售票系统为例。如图,用户向电影微服务发起了一个购票的请求。在进行购票的业务操作前,电影微服务需要调用用户微服务的接口,查询当前用户的余额是多少、是不是符合购票标准等。在这种场景下,用户微服务就是一个服务提供者,电影微服务则是一个服务消费者。
围绕该场景,先来编写一个用户微服务,然后编写一个电影微服务。
TIPS
服务消费者和服务提供者描述的只是微服务之间的调用关系,一般成对出现。例如本文,用户微服务是是电影微服务的服务提供者,电影微服务是用户微服务的服务消费者。很多初学者和笔者交流时,会描述提供者如何如何……仿佛消费者和提供者是微服务的固有属性,这是不对的——例如A调用B,B调用C,那么B相对A就是提供者,B相对C就消费者。

Spring Boot/Spring Cloud应用开发套路

Spring Boot/Spring Cloud时代后,应用开发基本遵循三板斧
  • 加依赖
  • 加注解
  • 写配置
至于你的业务代码,该怎么写还怎么写。
TIPS
对于懒人,可使用Spring Initilizr(IDEA、Spring Tool Suite等IDE上均有集成,也可在http://start.spring.io 使用网页版)创建应用,它会给你生成项目的依赖以及项目的骨架。后续,笔者会以番外的形式更新相关教程。

编写服务提供者【用户微服务】

1 创建一个Maven项目,依赖如下:
  • <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0  http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • <modelVersion>4.0.0</modelVersion>
  • <groupId>com.itmuch.cloud</groupId>
  • <artifactId>microservice-simple-provider-user</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <packaging>jar</packaging>
  • <!-- 引入spring boot的依赖 -->
  • <parent>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-starter-parent</artifactId>
  • <version>2.0.7.RELEASE</version>
  • </parent>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • <java.version>1.8</java.version>
  • </properties>
  • <dependencies>
  • <dependency>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-starter-web</artifactId>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-starter-data-jpa</artifactId>
  • </dependency>
  • <!-- 引入H2数据库,一种内嵌的数据库,语法类似MySQL -->
  • <dependency>
  • <groupId>com.h2database</groupId>
  • <artifactId>h2</artifactId>
  • </dependency>
  • <!-- 引入Lombok -->
  • <dependency>
  • <groupId>org.projectlombok</groupId>
  • <artifactId>lombok</artifactId>
  • <optional>true</optional>
  • </dependency>
  • </dependencies>
  • <!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
  • <dependencyManagement>
  • <dependencies>
  • <dependency>
  • <groupId>org.springframework.cloud</groupId>
  • <artifactId>spring-cloud-dependencies</artifactId>
  • <version>Finchley.SR2</version>
  • <type>pom</type>
  • <scope>import</scope>
  • </dependency>
  • </dependencies>
  • </dependencyManagement>
  • <!-- 添加spring-boot的maven插件,不能少,打jar包时得用 -->
  • <build>
  • <plugins>
  • <plugin>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-maven-plugin</artifactId>
  • </plugin>
  • </plugins>
  • </build>
  • </project>
其中, spring-boot-starter-web 提供了Spring MVC的支持; spring-boot-starter-data-jpa 提供了Spring Data JPA的支持; h2 是一种内嵌的数据库,语法和MySQL类似(笔者实在没有动力为了简单的演示再写一大堆内容去演示怎么安装MySQL数据库); lombok 则是一款开发利器,可以帮助你简化掉N多冗余代码。
WARNING
  • Lombok之前,必须为你的IDE安装Lombok插件!可参考: http://www.cnblogs.com/shindo/p/7550790.html
TIPS
  • Lombok快速上手: https://blog.csdn.net/motui/article/details/79012846
  • Lombok官方网站: https://projectlombok.org/
2 创建实体类:
  • @Entity
  • @Data
  • @NoArgsConstructor
  • @AllArgsConstructor
  • public class User {
  • @Id
  • @GeneratedValue(strategy = GenerationType.AUTO)
  • private Long id;
  • @Column
  • private String username;
  • @Column
  • private String name;
  • @Column
  • private Integer age;
  • @Column
  • private BigDecimal balance;
  • }
3 创建DAO:
  • @Repository
  • public interface UserRepository extends JpaRepository<User, Long> {
  • }
4 创建Controller:
  • @RequestMapping("/users")
  • @RestController
  • public class UserController {
  • @Autowired
  • private UserRepository userRepository;
  • @GetMapping("/{id}")
  • public Optional<User> findById(@PathVariable Long id) {
  • return this.userRepository.findById(id);
  • }
  • }
其中, @GetMapping,是Spring 4.3提供的新注解。它是一个组合注解,等价于 @RequestMapping(method=RequestMethod.GET),用于简化开发。同理还有 @PostMapping、 @PutMapping、 @DeleteMapping、 @PatchMapping等。
5 编写启动类:
  • @SpringBootApplication
  • public class ProviderUserApplication {
  • public static void main(String[] args) {
  • SpringApplication.run(ProviderUserApplication.class, args);
  • }
  • /**
  • * 初始化用户信息
  • * 注:Spring Boot2不能像1.x一样,用spring.datasource.schema/data指定初始化SQL脚本,否则与actuator不能共存
  • * 原因详见:
  • *  https://github.com/spring-projects/spring-boot/issues/13042
  • *  https://github.com/spring-projects/spring-boot/issues/13539
  • *
  • * @param repository repo
  • * @return runner
  • */
  • @Bean
  • ApplicationRunner init(UserRepository repository) {
  • return args -> {
  • User user1 = new User(1L, "account1", "张三", 20, new BigDecimal(100.00));
  • User user2 = new User(2L, "account2", "李四", 28, new BigDecimal(180.00));
  • User user3 = new User(3L, "account3", "王五", 32, new BigDecimal(280.00));
  • Stream.of(user1, user2, user3)
  • .forEach(repository::save);
  • };
  • }
  • }
@SpringBootApplication是一个组合注解,它整合了 @Configuration、 @EnableAutoConfiguration和 @ComponentScan注解,并开启了Spring Boot程序的组件扫描和自动配置功能。在开发Spring Boot程序的过程中,常常会组合使用 @Configuration、 @EnableAutoConfiguration和 @ComponentScan等注解,所以Spring Boot提供了 @SpringBootApplication,来简化开发。
在启动时,我们使用了 ApplicationRunnerinit(UserRepositoryrepository) 初始化了三条数据,分别是张三、李四、王五。 @Bean 则是一个方法注解,作用是实例化一个Bean并使用该方法的名称命名。类似于XML配置方式的 <beanid="init"class="...ApplicationRunner"/> 。
6 编写配置文件 application.yml :
  • server:
  • # 指定Tomcat端口
  • port: 8000
  • spring:
  • jpa:
  • # 让hibernate打印执行的SQL
  • show-sql: true
  • logging:
  • level:
  • root: INFO
  • # 配置日志级别,让hibernate打印出执行的SQL参数
  • org.hibernate: INFO
  • org.hibernate.type.descriptor.sql.BasicBinder: TRACE
  • org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
传统Web应用开发中,常使用properties格式文件作为配置文件。Spring Boot以及Spring Cloud支持使用properties或者yml格式的文件作为配置文件。
yml文件格式是YAML(Yet Another Markup Language)编写的文件格式,YAML和properties格式的文件可互相转换,例如本节中的application.yml,就等价于如下的properties文件:
  • server.port=8000
  • spring.jpa.show-sql=true
  • logging.level.root=INFO
  • logging.level.org.hibernate=INFO
  • logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
  • logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
从中不难看出,YAML比properties结构清晰;可读性、可维护性也更强,并且语法非常简洁。因此,本书使用YAML格式作为配置文件。但,yml有严格的缩进,并且key与value之间使用 : 分隔,冒号后的空格不能少,请大家注意

测试

访问 http://localhost:8000/users/1 ,可获得结果:
  • {"id":1,"username":"account1","name":"张三","age":20,"balance":100.00}

编写服务消费者【电影微服务】

我们已经编写了一个服务提供者(用户微服务),本节来编写一个服务消费者(电影微服务)。该服务非常简单,它使用RestTemplate调用用户微服务的API,从而查询指定id的用户信息。
1 创建一个Maven项目,ArtifactId是 microservice-simple-consumer-movie 。
2 加依赖:
  • <dependency>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-starter-web</artifactId>
  • </dependency>
3 创建实体类:
  • @Data
  • @AllArgsConstructor
  • @NoArgsConstructor
  • public class User {
  • private Long id;
  • private String username;
  • private String name;
  • private Integer age;
  • private BigDecimal balance;
  • }
4 创建启动类:
  • @SpringBootApplication
  • public class ConsumerMovieApplication {
  • @Bean
  • public RestTemplate restTemplate() {
  • return new RestTemplate();
  • }
  • public static void main(String[] args) {
  • SpringApplication.run(ConsumerMovieApplication.class, args);
  • }
  • }
5 创建Controller:
  • @RequestMapping("/movies")
  • @RestController
  • public class MovieController {
  • @Autowired
  • private RestTemplate restTemplate;
  • @GetMapping("/users/{id}")
  • public User findById(@PathVariable Long id) {
  • // 这里用到了RestTemplate的占位符能力
  • User user = this.restTemplate.getForObject("http://localhost:8000/users/{id}", User.class, id);
  • // ...电影微服务的业务...
  • return user;
  • }
  • }
由代码可知,Controller使用RestTemplate调用用户微服务的RESTful API。
6 编写配置文件 application.yml :
  • server:
  • port: 8010
拓展阅读
本文使用RestTemplate实现了基于HTTP的远程调用,事实上,Spring 5开始,WebFlux提供了Reactive的Web Client: WebClinet ,使用方式和RestTemplate基本类似,但性能更强,吞吐更好。有兴趣的可前往https://docs.spring.io/spring/do ... flux-client-builder 了解。在这里,笔者对WebClient做了一些简单的封装,也可关注:https://github.com/itmuch/thor-t ... /WebClientUtil.java

测试

访问: http://localhost:8010/movies/users/1 ,结果如下:
  • {"id":1,"username":"account1","name":"张三","age":20,"balance":100.00}

存在的问题

至此,我们已经实现了这个最简单的分布式应用,应用之间通过HTTP通信。代码非常简单,但这些简单的代码里,存在着若干问题:
1 应用没有监控,没有画板,一切指标都没有。在这个Growth Hack逐渐成为主流的时代,不弄个Dashboard把系统压力、QPS、CPU、内存、日活啥的可视化,你好意思出来混吗……
2 地址硬编码问题——电影微服务中将用户微服务的地址写死,如果用户微服务地址发生变化,难道要重新上线电影微服务吗?
你可能会质疑:用户微服务地址为什么会变,让它保持不变就行了啊,这不是问题。这里举两个例子:
例1:如果你用Docker,那么地址几乎每次启动都会变……
例2:你之前用的是TXYun,后来你想把用户微服务迁移到Aliyun。这个时候IP就会发生变化。我相信你不会乐意找到哪些服务调用了用户微服务的接口,然后所有调用用户微服务的服务统一修改地址……
3 负载均衡如何考虑?难道得在电影微服务和用户微服务之间加个NGINX做负载均衡吗?听起来是可行的,但如果有10000+服务(这并不夸张,我司的微服务数目是这个数字乘以N,N >= m,哈哈哈)那这个NGINX的配置得有多复杂……
4 服务之间没有容错机制,相信对技术有激情的你已经不止一次听过容错、降级、fallback、回退之类的词汇。
5 如果应用发生故障,你怎么迅速找到问题所在?
6 用户认证和授权呢?被狗吃了吗?
如上词汇,你可能看得懂,你也可能看不懂。没有关系,请继续阅读,笔者将会用通俗的语言去描述,在你看完本系列后,你会知道,原来那些所谓的高大上的理论、术语、技术,原来也就是这么回事儿。

配套代码

GitHub:
  •  
    https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-provider-user
  •  
    https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-consumer-movie
Gitee:
  •  
    https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-provider-user
  •  
    https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-consumer-movie

更多免费技术资料可关注:annalin1203

这篇关于Spring Cloud Finchley版-02-构建分布式应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/985384

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听