β

金融级开源分布式中间件 SOFA Boot 快速开始

Harries Blog™ 4120 阅读

在微服务 开发 中,Java 一直都是一门被广泛使用的语言,而 Java 的微服务框架如 Spring Boot 和 Spring Cloud 也具有广泛的受众,在蚂蚁金服内部长期的生产实践中创建了一套名为 SOFA(Scalable Open Financial Architect ure),本文讲解如何使用 SOFA Boot 快速开发 分布式 Web 应用程序。

SOFA Boot 是蚂蚁金服即将 开源 的一套微服务框架中的一个组件,开源地址: https :// git hub.com/al ip ay/sofa-boot

关于 Spring Boot 请参考 Spring Boot 快速开始指南

SOFA boot 简介

SOFA Boot 是蚂蚁金服基于 SpringBoot
的中间件轻量集成方案,与标准的 SpringBoot
工程无缝集成,提供了易用、统一的编程界面,具备以下特性:

  • 基于微服务框架 SpringBoot
    ,与 SpringBoot
    Spring
    框架无缝集成;
  • 集成蚂蚁金服中间件,包括 SOFA REST 、SOFA RPC、DMS(分布式消息服务)、DDS(分布式 数据 源服务) 等,提供统一编程界面;
  • 集成日志埋点工具 Tracer ,提供中间件统一日志埋点和上下文 ID;
  • 作为 SpringBoot
    上蚂蚁中间件的功能扩展,支持 FAT JAR
    包部署,支持的 Servlet
    容器有 Tom cat
    Jetty
    Undertow

准备环境

开发 SOFA boot 应用需要准备如下环境。

  • Java 7 或 Java 8
  • Maven 3.2.5

配置 Maven

修改 maven 配置 ~/.m2/setttings.xml

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
	 <offline>false</offline>
  <pluginGroups>
  <servers>
    <server>
      <id><a href="http://www.liuhaihua.cn/cdn-cgi/l/email-protection" data-cfemail="7a0202023a020202">[email protected]</a></id>
      <username>xxx</username>
      <password>xxx</password>
    </server>
  </servers>
  <mirrors>
  </mirrors>
  <profiles>
	<profile>
	<id>dev</id>
	<activation>
		<activeByDefault>true</activeByDefault>
	</activation>
	<repositories>
		<repository>
			<id>central_prod</id>
			<url>http://xxx/artifactory/repo</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>central</id>
			<url>http://xxx/artifactory/repo</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>snapshots</id>
			<url>http://xxx/artifactory/repo</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>central</id>
			<url>http://xxx/artifactory/repo</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>

	</pluginRepositories>
    </profile>
  </profiles>
</settings>

注意修改其中 server
标签下的配置, id
username
password
还有各种库的地址。

创建工程

SOFA Boot 支持创建 Web 工程和 core 工程。

使用下面的命令创建一个 Web 工程。

mvn archetype:generate -DarchetypeRepository=http://mvn.dev.alipay.net/artifactory/content/repositories/Alipay-Snapshot/ -DarchetypeGroupId=com.alipay.sofa -DarchetypeArtifactId=sofaboot-alipay-web-archetype -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeCatalog=internal

运行该命令会提示输入 groupId
artifactId
version
package

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[WARNING] Archetype not found in any catalog. Falling back to central repository.
[WARNING] Add a repsoitory with id 'archetype' in your settings.xml if archetype's repository is elsewhere.
Define value for property 'groupId': io.jimmysong.sofa
Define value for property 'artifactId': sofa-demo
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' io.jimmysong.sofa: :
Confirm properties configuration:
groupId: io.jimmysong.sofa
artifactId: sofa-demo
version: 1.0-SNAPSHOT
package: io.jimmysong.sofa
 Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: sofaboot-alipay-web-archetype:1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: io.jimmysong.sofa
[INFO] Parameter: artifactId, Value: sofa-demo
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: io.jimmysong.sofa
[INFO] Parameter: packageInPathFormat, Value: io/jimmysong/sofa
[INFO] Parameter: package, Value: io.jimmysong.sofa
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: groupId, Value: io.jimmysong.sofa
[INFO] Parameter: artifactId, Value: sofa-demo
[INFO] Parent element not overwritten in /Users/jimmysong/Workspace/SOFA/sofa-demo/app/endpoint/pom.xml
[INFO] Parent element not overwritten in /Users/jimmysong/Workspace/SOFA/sofa-demo/app/web/pom.xml
[INFO] Project created from Archetype in dir: /Users/jimmysong/Workspace/SOFA/sofa-demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.837 s
[INFO] Finished at: 2018-04-02T15:48:56+08:00
[INFO] Final Memory: 16M/309M
[INFO] ------------------------------------------------------------------------
  • groupId
    组织 名称,一般使用 域名 的倒叙,作为包名
  • artifactId
    :项目名称,会在当前 目录 下创建该名字的目录

项目 代码 生成完毕后将在运行该命令的运行路径下生成一个这样的项目结构(这是一个 Web 项目,所以项目中有个 web
目录):

sofa-demo
├── app
│   ├── endpoint
│   │   ├── pom.xml
│   │   └── src
│   │       └── main
│   │           ├── java
│   │           │   └── io
│   │           │       └── jimmysong
│   │           │           └── sofa
│   │           │               └── endpoint # SOFA REST 实现代码
│   │           │                   ├── constants
│   │           │                   │   ├── RestConstants.java
│   │           │                   │   └── URLConstants.java
│   │           │                   ├── exception
│   │           │                   │   ├── CommonException.java
│   │           │                   │   └── SofaRestExceptionHandler.java
│   │           │                   ├── facade
│   │           │                   │   ├── FaviconRestFacade.java
│   │           │                   │   └── SampleRestFacade.java
│   │           │                   ├── filter
│   │           │                   │   └── CommonContainerResponseFilter.java
│   │           │                   ├── impl
│   │           │                   │   ├── FaviconRestFacadeRestImpl.java
│   │           │                   │   └── SampleRestFacadeRestImpl.java
│   │           │                   ├── model
│   │           │                   │   └── DemoUserModel.java
│   │           │                   └── response
│   │           │                       ├── AbstractFacadeResp.java
│   │           │                       └── RestSampleFacadeResp.java
│   │           └── resources
│   │               └── META-INF
│   │                   └── sofa-demo
│   │                       └── sofa-demo-endpoint.xml
│   └── web
│       ├── pom.xml
│       └── src
│           ├── main
│           │   ├── java
│           │   │   └── io
│           │   │       └── jimmysong
│           │   │           └── sofa
│           │   │               └── Slite2WebSpringBootApplication.java # 启动函数
│           │   └── resources
│           │       ├── META-INF # Spring 配置文件存放处
│           │       │   └── sofa-demo
│           │       │       └── sofa-demo-web.xml
│           │       ├── config # 配置文件目录
│           │       │   └── application.properties # 配置文件,只有在本地启动应用时使用
│           │       ├── logback-spring.xml # 应用日志配置文件
│           │       └── static # Web 工程的静态文件目录
│           │           └── index.html
│           └── test # 应用的测试模块,内置启动了 Spring Boot 方便业务测试
│               └── java
│                   └── io
│                       └── jimmysong
│                           └── sofa
│                               └── web
│                                   └── test
│                                       ├── base
│                                       │   └── AbstractTestBase.java
│                                       └── usercases
│                                           └── SofaRestServiceTest.java
├── conf
│   ├── autoconf
│   │   ├── application.properties
│   │   ├── auto-config.xml
│   │   └── tenginx-conf
│   │       └── t-alipay-tengine.conf
│   ├── bin
│   │   ├── healthcheck.sh
│   │   ├── hook.sh
│   │   ├── nginx.sh
│   │   ├── startup.sh
│   │   └── util.sh
│   └── config
│       └── java_opts
└── pom.xml
 directories, 32 files

工程生成完毕,我们可以将该 Maven 工程导入到 IDE 中启动执行。

编译 打包

执行下面的命令将应用打包。

mvn package

我们再看看打包完成后的 target
目录的结构。

target
├── autoconf 
│   ├── application.properties # 配置文件,只有在本地启动应用时使用
│   ├── auto-config.xml # 自动生成的项目配置,包括定义配置文件路径
│   └── tenginx-conf
│       └── t-alipay-tengine.conf # 配置静态资源的访问和指定端口流量的转发
├── bin
│   ├── healthcheck.sh # 健康检查脚本
│   ├── hook.sh # 定义应用启动前、启动后、终止前、终止后调用的命令
│   ├── nginx.sh # nginx 启动脚本
│   ├── startup.sh # 启动脚本
│   └── util.sh # 工具脚本
├── boot
│   └── sofa-demo-web-1.0-SNAPSHOT-executable.jar # 可执行的 Fat Jar
└── config
    └── java_opts # 配置 JVM 参数,例如内存大小
 directories, 10 files

SOFA Boot 使用 外化配置的方式
,这些配置文件不是放在 Fat Jar
中的,我们可以看到 autoconf
bin
config
这三个目录也是我们创建工程时候自动创建的目录,它们也被拷贝到了 target
目录,这几个目录的作用如下:

  • autoconf:本地运行时配置
  • bin:启动和运行时检查
  • config:JVM 配置

以上的几个目录中的配置文件如 t-alipay-tengine.conf
auto-config.xml
中定义了变量,支持在编译打包的时候替换。

运行

在本地可以像普通的 Java 应用程序一样运行,使用 java -jar
指定 jar 包所在路径就可以直接运行了,配置文件。

java -jar target/boot/sofa-demo-web-1.0-SNAPSHOT-executable.jar

但是要使用 bin
目录下的脚本来实现运维功能,比如启动配置注入、健康检查等我们需要一台 Linux 机器,我选择在容器里运行。

target
目录中执行如下命令:

docker run -d -it --name=jdk --hostname=sofa-demo -p 8088:8080 -v `pwd`:/home jimmysong/jdk7:7u80 /bin/bash

上面命令的意思是使用 jimmysong/jdk7:7u80
镜像(该镜像基于 CentOS7 构建,大小为 281M),将容器的 主机 名设置为 sofa-demo
,容器名称为 jdk
(该镜像只提供 JDK7,不包含应用本身,当然我们也可以把应用打包进镜像中),将本地目录 target
下的文件挂载到容器中的 /home
目录下,并将容器内的 8080 端口映射为宿主机的 8088 端口以供我们在本地通过浏览器访问。

进入容器中启动应用。

docker exec -it jdk /bin/bash
cd /home/bin
./startup.sh
# 等待大概 3 秒钟
./healthcheck.sh
        -- SOFA Boot CheckService
        -- HealthCheck URL : http://localhost:8080/health
Health Check Result
SUCCESS

我们看到健康检查成功,表示应用已经成功启动。

此时访问 http://localhost:8088
将看到如下输出。

Static Resource Pages in SOFA Boot

部署

在编译和实际部署过程中需要进行配置项替换,配置替换的方式有如下几种:

  • 基于脚本做动态替换的配置方式
  • 在构建过程中, 让 Maven 利用 Filter 机制执行替换。
  • 基于 Profile 机制的配置
  • 基于公司的服务上线平台的配置方案
  • 基于 Profile + 远程拉取 Profile 配置的能力( 启动过程 中拉取)

Kubernetes 和 Service Mesh 的关系

实例 管理

仅从 Web 应用来说,Spring 基于 IoC(控制反转)和 AOP (面向切面编程),需要在 Java 代码中增加很多的注解,这些代码经过 Spring 框架的渲染后在可以为应用的运行时(各种Web容器,如Tomcat、Jetty等)注入各种配置信息。而 kubernetes 是将应用使用容器的方式来部署,将 Spring 中的各种注解给移动到了应用部署的层面,也就是说运维层,可以在每次发布的时候来定义服务的依赖信息,同时在 Service mesh 中控制服务之间的流量。

部署方式

  • 直接部署到宿主机的方式:如果是同样的服务的实例部署到了同一个主机上,必须保证应用启动的端口不冲突。
  • 使用 docker 镜像并使用 kubernetes 部署的方式:每个实例一个IP地址,无需关心端口冲突问题。

服务治理

Istio 中的 Pilot 是为不同的后端平台,比如 Kubernetes、Mesos、Cloudfoundry 提供一个统一的服务对象表示,运维人员可以通过配置服务对象的各种规则,Pilot 会把它们下发到每个 Envoy 中,这样来实现对 Service Mesh 的管理。

我们可以考虑将服务的治理功能与应用本身结构,通过类似 Istio
这样的架构,将应用透明

金融级开源分布式中间件 SOFA Boot 快速开始

后记

本月 SOFA 框架将会有一些列组件陆续开源,敬请关注 https://github.com/alipay

原文

https://jimmysong.io/posts/sofa-boot-quick-start/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。 PS:如果您想和业内技术大牛交流的话,请加qq群(474807195)或者关注微信公众号(AskHarries),谢谢!

转载请注明原文出处: Harries Blog™ » 金融级开源分布式中间件 SOFA Boot 快速开始

作者:Harries Blog™
追心中的海,逐世界的梦
原文地址:金融级开源分布式中间件 SOFA Boot 快速开始, 感谢原作者分享。

发表评论