上篇文章总结了《深入实践Spring Boot》的第一部分,这篇文章介绍第二部分:分布式应用开发,以及怎么构建一个高性能的服务平台。

主要从以下几个方面总结:

  • Spring Boot SSO
  • 使用分布式文件系统
  • 云应用开发
  • 构建高性能的服务平台

Spring Boot SSO

上篇文章提到了安全设计,使用Spring Security进行用户验证和权限验证,但一个企业级的应用系统可能存在很多应用系统,每个应用系统都需要设计安全管理,但不可能为每一个应用系统都设计一套安全管理,这样不但耗时耗力,而且要做重复的工作,也不适宜建立统一的用户中心。

可以使用单点登录SSO的方式建立一个登录认证系统,并且实现对用户的统一管理。本章在使用Spring Security安全管理的基础上,再结合OAuth2认证授权协议来实现的,它不但适用于大型的分布式管理系统,也适用于为第三方提供统一的用户管理和认证的平台。

作者给出了一个完整的实例,以模块化的设计方式进行实现,整个demo的代码可以在github上查看。(https://github.com/chenfromsz/spring-boot-sso

demo说明

我在本地运行了demo,通过chrome查看了系统间跳转的过程,先说明下模块的划分,然后看下运行效果。

项目 工程 类型 功能
数据库管理模块 mysql 程序集成 数据库管理
安全配置模块 security 程序集成 安全策略配置和权限管理
登录认证模块 login Web应用 SSO登录认证(80)
共享资源模块 resource Web应用 共享资源(8083)
客户端应用1 web1 Web应用 客户端1(8081)
客户端应用2 web2 Web应用 客户端2(8082)

访问首页时,跳转到登录页面,输入正确的账号、密码、验证码。
登录成功后,跳转到首页:

访问web1系统、web2系统时不需要重新登录,会自动登录:

「登录认证模块」主要包括验证用户账号、集成OAuth2服务端端功能。

「安全配置模块」是一个公共模块,集成了SSO客户端的安全策略配置和权限管理功能,供客户端引用。

「数据库管理模块」是一个公共模块,主要提供数据库的访问功能,供其他模块使用。

「共享资源模块」提供了一个简单的公共服务,2个客户端应用可通过spring-cloud-zuul直接调用。

后面会重点介绍下登录认证模块,其他模块比较简单,不再过多介绍。

模块化设计可以提高代码的复用性,避免重复开发,实例中的「数据库管理模块」和「安全配置模块」可以被其他模块共用,减少大部分重复工作。
作者的这种设计方式值得我们学习,在以后的系统设计中,应多借鉴这种方式。

登录认证模块

我画了一个流程图,先了解下用户认证、权限验证的基本过程:

整个处理流程,Spring Security都帮我们自动实现了,我们只需要对账号中心数据源、权限中心数据源进行配置和扩展,另外,可以对登录页面进行扩展,配置权限管理规则、防攻击策略、记住登录状态。

为了实现多个系统只需登录一次,需要集成OAuth2。添加spring-cloud-starter-oauth2依赖,编写一个配置类,继承AuthorizationServerConfigurerAdapter,并声明下@EnableAuthrizationServer来启用OAuth2的认证服务器功能。

OAuth2有很多授权机制,本例中使用authorization_code机制,具体配置就不过多说明了,可以参考下面的几篇文章:

[1] 初步理解Spring Security并实践
[2] security OAuth2.0 提供者实现原理
[3] jwt token介绍
[4] security OAuth2.0 jwt完美整合例子

使用分布式文件系统

有这样一个问题,如果上传文件,如上传图片,应该怎样保存,保存在哪里?

传统的做法一般都保存在Web服务器所在机器中。但随着业务的日益发展,可能上传的文件会累积越来越多,单台机器往往会不堪重负,再加上一些负载均衡的配置和服务,需要分布式文件系统解决。

在诸多分布式的文件系统中,FastDFS是比较优秀的分布式文件系统。FastDFS是一个完全开源的分布式文件系统,使用比较简单方便,而且性能也很优秀,存储容量和访问性能可按需求进行线性横向扩展。

FastDFS服务端和客户端的安排、配置、管理都比较简单,书中描述的也比较详细,就不在此赘述了。

云应用开发

Spring Cloud 是一套云应用开发工具集,为分布式的微服务开发提供了一整套简单易用的使用工具。Spring Cloud主要包括配置管理、服务发现、动态路由、负载均衡、断路器、安全管理、事件总线、分布式消息等组件的开发工具包。

Spring Cloud与Spring Boot 关系密切,能够臻于完美的几何使用。

本章重点介绍了配置服务、发现服务、动态路由和断路器、监控服务。

配置服务

一个项目工程总是需要一些配置,比如,要配置服务器的端口、访问数据库的参数等。一个大型的分布式系统可能存在很多这样需要配置的项目工程,配置管理是一个庞大的工程,需要一个单独的系统专门管理各个项目的配置。

通过Spring Cloud的配置管理,只需创建一个简单的工程,就可以实现分布式配置管理服务,同时还支持在线更新。

第一步,配置管理服务器
引入spring-cloud-config-server依赖,创建一个主程序:

@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigApplication{
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}

配置文件的存储目前支持使用本地存储、Git以及Subversion等方式。以Git方式为例,说明本地配置文件:

spring:
cloud:
config:
server:
git:
uri: https://github.com/chenfromsz/spring-cloud-config-repo
rabbitmq:
addresses: ${vcap.services.${PREFIX:}rabbitmq.credentials.uri:amqp://${RABBITMQ_HOST:192.168.1.215}:${RABBITMQ_PORT:5672}}
username: alan
password: alan

服务端会自动从指定的git地址获取配置信息。raabitmq的配置用于通知客户端应用配置更新。

第二步,配置管理的客户端
需要在工程中引入spring-cloud-starter-config依赖,使用配置管理服务之后,如果本地的配置文件与配置管理服务器的配置文件有相同的配置项,将优先使用配置管理服务器的配置项。

客户端的配置文件bookstrap.yml如下:

spring:
application:
name: data
profiles:
active: development
cloud:
config:
uri: http://localhost:8888
rabbitmq:
addresses: amqp://192.168.1.214:5672
username: alan
password: alan

其中,name用来指定应用的名称和配置文件的名称,uri设定配置服务服务端的地址和端口,profiles为使用配置文件名称的后缀部分,用于绑定不同的线上环境。

第三步,使用配置
如果配置文件中有cloud.config.test配置项,可以这样使用

@Value("${cloud.config.test:World!}") String msg;

另外,可以使用spring-cloud-bus-amqp依赖,通过事件总线的方式,实现在线更新所有客户端的配置。

发现服务

在分布式系统中,可能存在很多应用和服务,各个服务渎职自主地管理自身的数据。服务与服务之间,需要互相共享一些数据,传统的方式需要自己编写一些接口程序,还需要使用复杂的配置来实现,使用Spring Cloud可以轻易做到这些。

第一步,创建发现服务器
引入spring-cloud-starter-eureka-server依赖,创建一个简单的主程序即可:

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryApplication.class, args);
}
}

第二步,创建客户端
引入spring-cloud-starter-eurake依赖,主程序中加入@EnableDiscoveryClient启用发现服务的客户端。

配置文件如下:

eureka:
instance:
hostname: discovery
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://192.168.1.221:${server.port}/eureka/
动态路由和断路器

如何在服务间相互调用呢,可以使用动态路由、断路器和故障容错等功能。

引入spring-cloud-starter-zuul、spring-cloud-starter-hystrix依赖,添加@EnableZuulProxy和@EnableHystrix注解即可。

为了便于测试,可以通过共享Rest资源将repository的类直接暴露出来,很神奇吧,如下:

@RepositoryRestResource(collectionResourceRel="users",path="users")
public interface UserRepository extends GraphRepository<User> {
User findByName(@Param("name") String name); @Query("MATCH (u:User) WHERE u.name =~ ('(?i).*'+{name}+'.*') RETURN u")
Collection<User> findByNameContaining(@Param("name") String name); }

可以通过http://localhost/usershttp://localhost/users/123 之类的方式访问。

通过以下3种方式调用其他服务对外暴露的接口:

  • JavaScript:前端直接调用
  • RestTemplate:后端调用
  • FeignClient:特殊方式

以RestTemplate为例说明一个服务调用data服务的例子:

 @Autowired @LoadBalanced
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "getUserFallback")
public User getUserByName(String name) {
Map<String, Object> params = new HashMap<>();
params.put("name", name);
User user = restTemplate.getForObject("http://data/user/findByName?name={name}", User.class, params); return user;
}

上面例子中使用了@HystrixCommand用于实现断路器,当一个系统服务突然出现故障时,会自动阻断对服务的访问和调用,转而调用备用方法。

监控服务

分布式服务系统中运行着很多服务,必须有一个管理机制和方法,能够一目了然地随时了解各个服务的运行情况及其健康指数。

使用Spring Cloud的监控服务,可以实时监控应用的运行情况。使用很简单,引入spring-cloud-starter-hystrix-dashboard依赖,创建一个主程序即可:

@SpringBootApplication
@Controller
@EnableHystrixDashboard
public class HystrixApplication{
@RequestMapping("/")
public String home() {
return "forward:/hystrix";
} public static void main(String[] args) {
SpringApplication.run(HystrixApplication.class, args);
}
}

具体监控指标可参看官网文档。

构建高性能的服务平台

使用Spring Cloud开发的微服务,其独立而又相对隔离的特性,与Docker的理念有异曲同工之妙,所以使用Docker发布微服务,能够发挥其最大的优势,并且可以非常轻易地构建一个高性能和高可用的服务平台。

Docker可以很方便地创建和管理镜像,以及管理已经生成的和正在运行的容器。镜像是一种文件存储方式,可以把许多文件做成一个镜像文件。容器是镜像运行的一个实例,运行一个镜像,就会生成一个容器,容器生成之后,就可以在容器中管理应用系统了。

Docker的安装和发布服务,网上的资料很多,这里就不赘述了。

另外,可以使用其他一些服务管理工具来构建高性能和高可用的服务平台。docker-compose工具是Docker容器管理工具集,可以很方便地用来创建和重建容器、执行启动和停止容器等管理操作,以及查看整个服务体系的运行情况和输出日志等。使用docker-compose工具,只要一条指令就能启动整个分布式服务体系。

通过本篇文章的介绍,大家可以感受到Spring Cloud在构建分布式应用时提供的便捷性,减少了大量的工作量。同时为我们考虑了方方面面,增强了系统的稳定性、高性能。
作者把所有代码都上传到github,大家可以直接运行demo深入了解。
[1] Spring Boot SSO:https://github.com/chenfromsz/spring-boot-sso
[2] 云应用开发:https://github.com/chenfromsz/spring-boot-cloud

《深入实践Spring Boot》阅读笔记之二:分布式应用开发的更多相关文章

  1. Spring Boot实战笔记(二)-- Spring常用配置(Scope、Spring EL和资源调用)

    一.Bean的Scope Scope描述的是Spring容器如何新建Bean实例的.Spring的Scope有以下几种,通过@Scope注解来实现. (1)Singleton:一个Spring容器中只 ...

  2. spring boot 学习笔记(二)之打包

    一.叙述 spring boot 在 pom 中可以配置成  packaging 为 jar ,这样打包出来的就是一个 jar 包,可以通过 Java 命令直接运行, Java 命令为: java - ...

  3. spring boot学习笔记(二)创建spring boot项目

    用eclipse(需要用高版本,要不然弄不出来):new →Spring Sarter Project 用IDEA:一般默认 一般默认 入门级的先 剩下的一般默认... 一.项目至少有下面的东西,里面 ...

  4. 我的第一个spring boot程序(spring boot 学习笔记之二)

    第一个spring boot程序 写在前面:鉴于spring注解以及springMVC的配置有大量细节和知识点,在学习理解之后,我们将直接进入spring boot的学习,在后续学习中用到注解及其他相 ...

  5. Java框架spring Boot学习笔记(二):Hello Spring Boot、以及项目属性配置

    新建一个新建一个SpringBootTest工程 新建一个HelloController.java文件 package com.example.demo; import org.springframe ...

  6. Spring Boot学习笔记(二)——HelloWorld实现

    提示:要在Eclipse里使用Spring Boot,首先要安装STS插件,前面我们已经安装了STS插件了,可以创建Spring Boot项目了. 1.创建项目: 新建项目,选择Spring Boot ...

  7. spring boot入门笔记 (二) - application.properties配置文件

    项目最重要的一个东西,用来定义整个项目的一些东西(端口.访问项目的名称.数据源.日志.集成mybatis等框架.静态资源目录.thymeleaf.热部署等),很重要很重要的. #整个项目的端口号,默认 ...

  8. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  9. 《深入实践Spring Boot》阅读笔记之三:核心技术源代码分析

    刚关注的朋友,可以回顾前两篇文章: 基础应用开发 分布式应用开发 上篇文章总结了<深入实践Spring Boot>的第二部分,本篇文章总结第三部分,也是最后一部分.这部分主要讲解核心技术的 ...

随机推荐

  1. 手摸手教你微信小程序开发之自定义组件

    前言 相信大家在开发小程序时会遇到某个功能多次使用的情况,比如弹出框.这个时候大家首先想到的是组件化开发,就是把弹出框封装成一个组件,然后哪里使用哪里就调用,对,看来大家都是有思路的人,但是要怎样实现 ...

  2. Sqoop工具

    简介 SQOOP是用于对数据进行导入导出的. (1)把MySQL.Oracle等数据库中的数据导入到HDFS.Hive.HBase中 (2)把HDFS.Hive.HBase中的数据导出到MySQL.O ...

  3. VM及centOS系统安装

    虚拟机安装linux及配置

  4. centos7上安装0penStack

    centos7上安装0penStack author:headsen chen 2017-10-09  20:41:54 个人原创,欢迎转载,请注明作者,出去,否则依法追究责任 一,准备工作(配置ip ...

  5. 框架开发之——AngularJS+MVC+Routing开发步骤总结——5.14

    1.延续MVC的观念:包括路由映射的编写,Controller的内容,具体View页面js的分离. 2.结合AngularJS做前端,后端使用Node.Js的写法,引入MVC框架,进行快速的开发. 步 ...

  6. 笔记:Hibernate 持久化类标注说明

    持久化类标注 标注 @Entity:注解声明该类是一个Hibernate的持久化类 标注 @Table:指定该类映射的表 参数 name:指定映射数据库表的名称 参数 uniqueConstraint ...

  7. JAVAEE——BOS物流项目08:配置代理对象远程调用crm服务、查看定区中包含的分区、查看定区关联的客户

    1 学习计划 1.定区关联客户 n 完善CRM服务中的客户查询方法 n 在BOS项目中配置代理对象远程调用crm服务 n 调整定区关联客户页面 n 实现定区关联客户 2.查看定区中包含的分区 n 页面 ...

  8. Python中列表、元组、字典增删改查基本区别

    1.定义: 列表:num = ["a","b"."c"] ##定义后可增删改查 元组:num = ("a"," ...

  9. (转)关于 awk 的 pattern(模式)

    本文转自chinaunix http://bbs.chinaunix.net/thread-4246512-1-1.html   作者reyleon 我们知道, awk程序由一系列 pattern 以 ...

  10. (转)SQLite内置函数

    一.聚合函数: SQLite中支持的聚合函数在很多其他的关系型数据库中也同样支持,因此我们这里将只是给出每个聚集函数的简要说明,而不在给出更多的示例了.这里还需要进一步说明的是,对于所有聚合函数而言, ...