Tag Archives: Java

Java WEB系统微服务化迁移

  1. Docker
  2. 微服务
  3. Spring-Boot

支撑互联网公司运行的庞大后端服务系统经历了原始的BS架构设计、前后端分离、模块化组件、系统分层设计的进化,从计算资源的虚拟化到今天容器技术的应用,互联网一直在朝着资源高效配置、分布式集群服务的方向进发。

Docker作为当下最流行的容器化技术,相比于运行在实体物理机上的虚拟机技术,它具有轻量级资源隔离、快速部署、持续交付、版本控制、 可移植、开放技术等特点。

如果采用虚拟机技术去部署一套系统,需要几个步骤:

1、分配物理资源(CPU\内存\网络)

2、开机启动运行

3、安装系统运行时支撑环境(模版)

4、发布生产系统

5、上线。

采用Docker需要如下几个步骤:

1、拉取Docker Image

2、发布生产系统

3、上线

相比来看可能就会发现,Docker相当于把最繁琐最耗时的工作帮助我们解决了。Docker运行在(特定)操作系统之上,只需要一条命令即刻启动;通过Docker Image将运行时配置、依赖管理、版本管理集成一个Dockerfile描述文件中标准化,快速解决原始虚拟机技术中的1、2、3步骤。如果再搭配Google出品的Kubernetes容器管理工具更加得心应手。

与Docker并行出现一个架构模式-微服务,它并不是一种全新的架构体系,更确切的说是一种架构的思考。在经历了模块化、组件化、服务化之后,系统的架构设计实现复杂、服务调用关联度高等问题困扰着一个系统的稳定性和开发难度。微服务是在原有的服务治理的基础上,将原有系统服务的粒度进行再切分使得服务之间的耦合性降至最低,同时不依赖于过多的外部运行时环境,对外暴露的输入输出可能只是一个JSON、XML数据集,可以实现大规模的快速部署运行。这些特点与Docker的容器化优势不谋而合,这也是当前微服务实践采用比较多的一种方式。

Spring Boot在微服务概念出现之前已经发布了有一段时间,但并没有大行其道,大家对于Java Web的项目更倾向于原有Servlet Container Server的部署模式。随着微服务的出现,Spring Boot再次引起了大家的注意,同时Spring在被收购后也在朝着云服务商的方向上进发,推出了自己的云服务平台。

相比一切全新的服务系统,遗留的Java WEB系统如何进行更好的迁移使用微服务,是需要考虑的一大问题。当前的项目中框架采用了Freemarker+Spring+Hibernate的方式,Spring的配置是原有的XML配置方式,与Spring-Boot推荐的注解配置相比,迁移难度较大。

Spring-Boot使用注解配置剥离了XML的配置方式,使用内嵌式Servlet Container(Jetty\Tomcat\Undertow)来实现服务的HTTP通信、监控、交互。与此相对照,能否维持XML配置不变,仅使用内嵌Servlet Container来提供服务呢?答案是:可以。

采用Tomcat Embed作为默认的Servlet Container,通过Tomcat Bootstrap中Host、Port配置来实现HTTP服务,指定WEB路径的方式来提供Spring XML配置部分和其他WEB资源,这样就基本实现了原有Java WEB系统的服务化迁移。

在迁移测试过程中,也遇到了几个坑。

1、Gradle编译工具对JAR包的支持度不够完善,需要额外的插件来实现Eclipse FatJar的功能。

2、如果自定义Jar合并时,一定要注意Spring Schema文件的合并。在不使用插件的情况下,会导致spring schema XSD文件的丢失。需要在插件支持下通过tramformer来合并。

如果单独使用Maven来打包之需要通过修改POM文件来实现。

相关资料     Docker Spring-Boot Gradle FatJar Plugin Tomcat Embed

OAuth2协议和Spring Security OAuth2实现

OAuth2协议在API访问授权中广为使用,Google、Facebook、微博、腾讯的公开API也都使用它。虽然在使用上有些复杂,尤其是服务器端的使用更为繁琐,但它在权限授予、资源访问限制上的优势让其使用广泛。

OAuth2的协议流程如下:

oauth-protocol-flow

以国内的微博为例,

Resource Owner=微博用户;

Client=第三方应用,如Fuubo、Weico;

Authorization Server=微博平台授权服务器;

Resource Server=访问微博、用户信息等资源的服务器

当开发者决定要开发一款基于微博的应用时,需要到http://open.weibo.com去填写一些资料,比如应用名称、类型、访问哪些资源,提交相关信息之后,微博后台会创建应用,分配一个client_idclient_secret,这两个字段对你的应用至关重要,以后会派上用场。

下面就开始正式的OAuth2协议流程:

A、开发者构造Authorization Request(请求微博用户授权),如果此时微博用户A没有登录会直接跳转到微博登录页面,如果已经登录会跳转到授权页面,如图所示。

OAuth2_intro

此时会列出开发者在申请应用时选择要访问的权限,除了必须的权限以外微博用户A可以不勾选部分权限,这样开发者就无法读取相对应的资源。

B、 Authorization Grant(微博用户授予访问权限),如果微博用户A点击“授权”,开发者将获得这个微博用户A的微博、用户信息等资源的访问,开发者将获取到一枚临时code。点击“取消”将拒绝资源的访问。

C、Authorization Grant(请求微博平台授权)开发者拿着微博用户A授权之后获取的临时code,访问微博平台授权服务器,获取“永久”(也有时间限制)访问微博用户A的授权。

D、Get Access Token(微博平台授予微博用户A的访问)微博平台授权服务器检查微博用户A的临时code,检查通过后给开发者返回一个“永久”的Token

E、Take in Access Token(发起携带Token的请求),开发者在访问资源的请求中带上Token

F、Protected Resource(返回微博用户A的微博、用户信息等资源)资源服务器检查Token,根据请求URL的不同返回微博用户A的相应资源信息。

通过这几步就实现了微博用户、微博平台、第三方开发者之间的访问授权,当然如果是用户B使用开发者开发的这款应用还需要进行如上所述的步骤。

以上简单介绍了OAuth协议中最复杂的一种授权访问方式(Authorization Code Grant),也是第三方应用用的最多的一种,其他三种对于特定环境下建议使用,比如:

Implicit Grant-多用于浏览器内的应用,可直接回调获取到Token,简单方便。

Resource Owner Password Credentials Grant-用于第三方应用处于可控的风险之下,多用于内部系统的互访问。

Client Credentials Grant-顾名思义,多用于客户端的授权访问,客户端必须保证在开发者手中。

OAuth2协议的可以访问地址查看。

=========================================================================

Spring在security project的基础上实现了OAuth2 的Server端,同时支持四种授权方式,参考了网上的不同示例但都没有完美支持所有方式,阅读官方文档参考源码后完整构建了OAuth2的Server端。

1、代码示例基于

spring-core v4.2.3

spring-security v3.2.x

spring-security-oauth v2.0.8

2、自定义Endpoint用于回调、跳转、登录等功能:

/login-用户form登录action[POST]

/msg/code-授权回调页

/msg/error-授权访问错误页

/msg/login_success-用户form登录成功回调页

/msg/login_error-用户form登录失败回调页

3、OAuth ClientDetail、Token数据库表脚本

访问地址下载。

4、web.xml中除了Spring基础配置还需要添加Spring Security相关配置

 

5、Spring token存储、读写验证服务。

6、OAuth2授权时拒绝、授权各自不同的Handler以及触发处理

7、用户form登录时成功、失败各自不同的Handler以及触发处理

8、用户form登录filter捕获、安全规则

9、用户认证

10、应用认证filter捕获

11、应用认证服务管理

12、OAuth2认证服务器

至此,Spring OAuth2的基础配置已经完成。在数据库的oauth_client_details中添加demo应用的详细信息,如client_id、client_secret、redirect_uri。

=========================================================================

验证配置过程:

1、用户Form登录:

POST http://example.com/login

username:xxx

password:XXX

2、OAuth2 implicit方式用户授权

GET http://example.com/oauth/authorize?redirect_uri=http://example.com/msg/code&client_id=ccc&response_type=token

3、用户授权回调action(浏览器会直接跳转,若为Rest工具手动执行以下请求)

POST http://example.com/oauth/authorize

user_oauth_approval:true

4、授权成功,回调http://example.com/msg/code#access_token=xxxxxxxxx&&expired_in=48400

注意回调时不会将access_token作为queryParam回调。

如果能够回调成功,说明配置OAuth2配置成功,其他三种方式仅限于2、3、4步的微小区别。

~如上文配置中提到的Auth Decision Manager,上述配置只是完成了Spring OAuth2的基础部分,具体到哪个应用能够访问哪些资源,资源权限的定义规则还没有给出,这就是授权访问中资源服务器的定义了。

相比于PHP、Python对于OAuth2协议的简单实现,Spring的实现略显笨重,配置复杂。Spring自成一体的闭合,将OAuth2基于Security进行实现,而且又对LADP等协议有不同的接驳,这或许也是Spring中间件越做越重的归宿~

当然Java方向上还有一个OAuth2的实现也可以关注,Apache Oltu

tiantongyuan-south

Java的位运算、移位运算

上个月在做蓝牙通讯协议实现时数据操作基本处于Byte级别,所以用到了大量的位运算,恰巧看到这篇简单而又容易遗忘的基础点,所以翻译一下,顺便熟悉熟悉。

Java的位运算和移位运算非常强大,它可以在bit级别上使用int、long、short、byte以及boolean类型的数据,而且相比其他运算方式,位运算和移位运算的速度要快很多。但是很多Java程序员却对此了解不多,尤其时那些没有接触过C、C++语言的程序员。当然对于在学习Java之前已经了解了C、C++的程序员来说就没有那么陌生了,因为这些运算基本与C类似。

在许多面试题中也会经常出现这种运算题目。这个实例代码主要时为了快速的了解Java的位运算符之间的不同,以及如何使用他们,其次我们也会介绍一下无符号移位和有符号的移位运算。

基础

在介绍位运算和移位运算之前,你必须区分二进制、位、字节和位运算。良好的二进制运算基础对理解位运算将大有裨益。

1)二进制数据只会有两种0、1两种位,这也是为什么叫做二进制位的原因。

2)二进制的算术运算

0 + 0 = 0

1 + 0 =  1

1 + 1 =  10

3)取反运算:会将0改为1、1改为0,它用~来表示

4)OR运算:如果任一操作数中有1返回1;如果操作数均为0则返回0

5)AND运算:如果操作数均为1返回1,否则返回0

6)XOR运算:如果两个操作数相同则返回0;否则返回1,比如1XOR1返回0,1XOR0返回1,0XOR1返回1,0XOR0返回0

7)Java中的整数类型都是有符号的,其中最高位表示正负,高位为1表示负数,高位为0表示正数。

8)Java中的负数用2的补码来表示。2的补码=1的补码+1,1的补码全为0