上篇文章总结了《深刻实践Spring Boot》的第一部分,这篇文章介绍第二部分:分布式应用开发,以及怎么构建一个高性能的服务平台。html
主要从如下几个方面总结:前端
上篇文章提到了安全设计,使用Spring Security进行用户验证和权限验证,但一个企业级的应用系统可能存在不少应用系统,每一个应用系统都须要设计安全管理,但不可能为每个应用系统都设计一套安全管理,这样不但耗时耗力,并且要作重复的工做,也不适宜创建统一的用户中心。vue
可使用单点登陆SSO的方式创建一个登陆认证系统,而且实现对用户的统一管理。本章在使用Spring Security安全管理的基础上,再结合OAuth2认证受权协议来实现的,它不但适用于大型的分布式管理系统,也适用于为第三方提供统一的用户管理和认证的平台。java
做者给出了一个完整的实例,以模块化的设计方式进行实现,整个demo的代码能够在github上查看。(https://github.com/chenfromsz/spring-boot-sso)mysql
我在本地运行了demo,经过chrome查看了系统间跳转的过程,先说明下模块的划分,而后看下运行效果。git
项目 | 工程 | 类型 | 功能 |
---|---|---|---|
数据库管理模块 | mysql | 程序集成 | 数据库管理 |
安全配置模块 | security | 程序集成 | 安全策略配置和权限管理 |
登陆认证模块 | login | Web应用 | SSO登陆认证(80) |
共享资源模块 | resource | Web应用 | 共享资源(8083) |
客户端应用1 | web1 | Web应用 | 客户端1(8081) |
客户端应用2 | web2 | Web应用 | 客户端2(8082) |
访问首页时,跳转到登陆页面,输入正确的帐号、密码、验证码。
登陆成功后,跳转到首页:github
访问web1系统、web2系统时不须要从新登陆,会自动登陆:web
「登陆认证模块」主要包括验证用户帐号、集成OAuth2服务端端功能。spring
「安全配置模块」是一个公共模块,集成了SSO客户端的安全策略配置和权限管理功能,供客户端引用。sql
「数据库管理模块」是一个公共模块,主要提供数据库的访问功能,供其余模块使用。
「共享资源模块」提供了一个简单的公共服务,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/users , http://localhost/users/123 之类的方式访问。
经过如下3种方式调用其余服务对外暴露的接口:
以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