This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-docs.git
The following commit(s) were added to refs/heads/master by this push:
new 131d85d add fence and best practices (#355)
131d85d is described below
commit 131d85d66ec2992f390f3af51a1e9e89578c7f73
Author: liubao68 <[email protected]>
AuthorDate: Fri Oct 18 16:24:27 2024 +0800
add fence and best practices (#355)
---
.../zh_CN/docs/best-practise/about-fence.md | 56 +++++
.../zh_CN/docs/best-practise/authentication.png | Bin 0 -> 85676 bytes
.../zh_CN/docs/best-practise/authorization.png | Bin 0 -> 79697 bytes
.../docs/best-practise/design-observability.md | 147 +++++++++++
.../zh_CN/docs/best-practise/design-resilience.md | 72 ++++++
.../zh_CN/docs/best-practise/design-security.md | 268 +++++++++++++++++++++
.../zh_CN/docs/best-practise/fence-deploy.png | Bin 0 -> 11494 bytes
.../zh_CN/docs/best-practise/fence-home.png | Bin 0 -> 85454 bytes
.../zh_CN/docs/best-practise/observability.png | Bin 0 -> 136518 bytes
.../zh_CN/docs/best-practise/resilience-change.png | Bin 0 -> 16410 bytes
.../zh_CN/docs/best-practise/resilience-growth.png | Bin 0 -> 21488 bytes
.../zh_CN/docs/best-practise/resilience-new.png | Bin 0 -> 29504 bytes
.../zh_CN/docs/best-practise/scaffolding.md | 19 ++
java-chassis-reference/zh_CN/mkdocs.yml | 34 +--
14 files changed, 582 insertions(+), 14 deletions(-)
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/about-fence.md
b/java-chassis-reference/zh_CN/docs/best-practise/about-fence.md
new file mode 100644
index 0000000..d6c7093
--- /dev/null
+++ b/java-chassis-reference/zh_CN/docs/best-practise/about-fence.md
@@ -0,0 +1,56 @@
+# Fence项目介绍
+
+[ServiceComb Fence](https://github.com/apache/servicecomb-fence) 是包含Java
Chassis 3最佳实践的应用开发脚手架,它可以帮助开发者快速构建包含微服务后端、微服务前端和基础原子服务的项目工程。
+
+基于Fence,可以快速构建一个韧性、安全和敏捷的微服务项目工程。Fence的核心设计包括韧性架构、安全认证、可观测性、过载防护等方面,它主要由如下几个微服务组成:
+
+* edge-service:
微服务网关。微服务网关负责接收用户的请求,并将请求转发给对应的微服务前端和微服务后端进行处理。微服务网关还负责认证鉴权、过载防护等方面的系统功能。
+* authentication-server: 认证服务。认证服务提供基于Oauth2的认证能力,实现了基础的用户、角色管理,认证和授权等功能。
+* resource-server: 资源服务。资源服务是一个示例项目,用户新开发的服务都属于资源服务,这个服务可以作为新增服务的模板。
资源服务实现了一些基础的鉴权功能,提供基于Yaml配置和Java Annotation声明的权限管理机制。
+* admin-service:
微服务管理服务。微服务管理服务提供微服务管理和系统运维功能。包括管理和查看服务列表、管理和查看服务配置、系统问题分析和定位能力。
+* admin-website: 微服务管理服务的前端。这是一个基于 [OpenTiny](https://opentiny.design/)
开发的静态页面服务,实现微服务管理服务的Web前端。 它可以作为用户新增前端的模板,提供了基础的Web前端开发框架,包括菜单、导航等方便阅读和扩展的代码框架。
+
+Fence还依赖中间件服务Zookeeper和数据库MySQL。
+
+Fence项目遵循*约定优于配置*原则,定义了日志配置、Web配置、路由配置、代码结构等相关规范,以更加简洁的实现可观测性、过载防护等功能。
+
+## 下载和运行Fence项目
+
+在下载和运行Fence项目前,假设您已经体验过Java Chassis的快速入门,并已经安装和设置好JDK 17、Maven、Git、IDEA等开发环境。
+
+* 下载和安装 [Zookeeper](https://zookeeper.apache.org/releases.html)
+
+ Fence 使用Zookeeper作为注册中心和配置中心,可以参考官网链接下载和安装。
+
+* 下载和安装 [MySQL](https://www.mysql.com/downloads/)
+
+ Fence 使用MySQL作为数据库,可以参考官网链接下载和安装。
+
+* 下载和安装OpenTiny(可选)
+
+ Fence前端框架使用OpenTiny要修改编译源码需要下载和安装OpenTiny相关开发环境。详细可以参考[Open Tiny
Pro的官网说明](https://opentiny.design/vue-pro/docs/start) 。
+
+* 下载Fence代码并编译
+
+ ```
+ git clone https://github.com/apache/servicecomb-fence.git
+ cd servicecomb-fence
+ mvn clean install
+ ```
+
+* 初始化数据库
+
+ authentication-server依赖数据库,找到 src/resource/sql/user.sql,在数据库执行该初始化脚本。
+
+* 启动和运行
+
+ 可以使用 `build_and_run.bat` 脚本启动项目,也可以使用 IDEA 打开 Fence工程,启动Fence的每个微服务。
+
+* 进入Fence管理界面。
+
+ 输入:http://localhost:9090/ui/admin/ , 登录系统后可以看到如下界面
+ 
+
+## 后续
+
+在接下来的内容里面,我们将逐步从韧性架构设计、安全认证设计、可观测性设计、过载防护设计、契约优先开发、项目脚手架等方面,专题介绍Fence项目。
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/authentication.png
b/java-chassis-reference/zh_CN/docs/best-practise/authentication.png
new file mode 100644
index 0000000..be94dfc
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/authentication.png differ
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/authorization.png
b/java-chassis-reference/zh_CN/docs/best-practise/authorization.png
new file mode 100644
index 0000000..91246c0
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/authorization.png differ
diff --git
a/java-chassis-reference/zh_CN/docs/best-practise/design-observability.md
b/java-chassis-reference/zh_CN/docs/best-practise/design-observability.md
new file mode 100644
index 0000000..fb6b839
--- /dev/null
+++ b/java-chassis-reference/zh_CN/docs/best-practise/design-observability.md
@@ -0,0 +1,147 @@
+# 可观测性设计
+
+狭义的可观测性,指日志、调用链和指标,广义的可观测性则包含更多的内容,一般的,应用程序暴露出来的便于理解其运行状态、运行轨迹、内部结构和功能集合的信息,都是可观测性的范围,本文只讨论狭义的可观测性。日志揭露了应用程序内部运行的轨迹,通过异常日志,可以理解错误产生的原因;调用链反映的是一次业务操作经过的关键处理节点,可以帮助快速确定问题发生的边界;指标反映错误发生时应用程序的当前或者历史状态,帮助分析需要一定的时间或者流量积累才会发生的问题,比如过载问题、性能问题等。可以看出,为了分析故障,具备可观测性能力非常重要。
+
+微服务系统具备复杂的调用关系和分布式部署特征,为了更好的分析和处理日志、调用链和指标,通常会部署ELK、SkyWalking和Prometheus等外部系统。
这些系统完全搭建起来,会花费数十万每年的计算成本,而且很可能并没有显著提升日常问题定位的效率,不恰当的使用还可能会引入性能问题。针对问题定位难的情况,ServiceComb
Fence提供了非常简单高效,而且低成本的解决方案。由于采集的数据,都是和Java
Chassis运行过程和系统架构强相关的,也避免了采集海量无关数据,使得数据对于问题分析更具有针对性,能够更加快速识别问题根因。
+
+## 问题定位流程
+
+在很多组织里面,问题定位都是由不太熟悉系统结构和技术细节的运维人员开始的,或者是由工作交接后刚刚接触系统的新人开始的,这给快速定界问题,收集和问题相关的信息带来了巨大的挑战。一个问题从发现到传递给责任模块,数个小时的时间就过去了。
设计一个简单的问题定位流程,快速定界问题和收集关联信息,是可观测系统搭建的起点。
+
+当用户识别到一个故障,比如交易失败,在系统层面,会对应到一次系统请求的失败。在系统设计之初,会采用一个请求标识将用户故障和系统请求关联起来,即
`TraceId`, 这个是所有调用链系统设计的基础。 通常建议前端在发送请求的时候,都携带 `TraceId`,
便于将前后端请求进行关联。在前端未按照要求携带 `TraceId` 的情况下,Java Chassis会在应用网关 Edge Service生成
`TraceId`, 并在给前端响应的HTTP头中携带 `TraceId`。 当用户识别到一个故障,可以通过浏览器等前端工具获取到 `TraceId`。
问题定位的起点是获取`TraceId`。
+
+
+
+在管理控制台,输入`TraceId` 和问题发生大概时间,可以检索出关键的调用链信息和关键日志信息。
通过调用链信息,可以知道请求的执行轨迹和发生问题的节点,通过关键日志信息,能够快速确定问题根因。
对于一些简单常见的问题,经过这个简单的步骤,就能够确定问题根因。
+
+对于一些复杂的问题,需要获取上下文日志或者指标来进行深入的分析,运维人员可以在检索结果里面将完整的日志文件和指标信息下载下来,提供给故障服务的技术人员。
+
+从上面的过程可以看出,运维人员在不理解系统实现细节的情况下,也能快速定界和定位一些简单问题,并能够快速收集详细的和问题强相关的信息提供给技术人员做进一步处理。
+
+## 实现原理
+
+Java
Chassis在设计之初,就内置了大量的可观测能力。使用上述流程,无需部署ELK、SkyWalking和Prometheus去采集数据,也不需要集成这些工具的SDK或者Agent。
通过一些开发规范约束和`可观测API`就能够实现一个简单高效和易用的定位系统。
+
+Java
Chassis通过集成[应用性能监控](../general-development/metrics.md)、[微服务调用链](../general-development/microservice-invocation-chain.md)来生成调用链和指标,日志则使用
`slf4j` 来记录。 这些数据构成了可观测的基础, 接下来就是如何存储和采集这些数据。
+
+通过配置 `log4j2` , 可以将日志、调用链和指标都输出到日志文件。
特别的,该日志配置约束了数据存储的规则、路径,为`可观测API`提供了简单的实现方案。
+
+```xml
+<Configuration>
+ <Properties>
+ <property name="FILE_PATH" value="./logs/admin-website"/>
+ </Properties>
+
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss}
[%X{SERVICECOMB_TRACE_ID}][%p][%t][%c:%L] %m%n"/>
+ </Console>
+
+ <RollingFile name="RootLog" fileName="${FILE_PATH}/root.log"
+ filePattern="${FILE_PATH}/root-%d{yyyy-MM-dd-HH}.log">
+ <PatternLayout pattern="%-d{yyyy-MM-dd-HH:mm:ss}
[%X{SERVICECOMB_TRACE_ID}][%p][%t][%c:%L] %m%n"/>
+ <Policies>
+ <TimeBasedTriggeringPolicy interval="3"/>
+ </Policies>
+ <DefaultRolloverStrategy max="100"/>
+ </RollingFile>
+
+ <RollingFile name="TraceLog" fileName="${FILE_PATH}/trace.log"
+ filePattern="${FILE_PATH}/trace-%d{yyyy-MM-dd-HH}.log">
+ <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %m%n"/>
+ <Policies>
+ <TimeBasedTriggeringPolicy interval="3"/>
+ </Policies>
+ <DefaultRolloverStrategy max="100"/>
+ </RollingFile>
+
+ <RollingFile name="MetricsLog" fileName="${FILE_PATH}/metrics.log"
+ filePattern="${FILE_PATH}/metrics-%d{yyyy-MM-dd-HH}.log">
+ <PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} %m%n"/>
+ <Policies>
+ <TimeBasedTriggeringPolicy interval="3"/>
+ </Policies>
+ <DefaultRolloverStrategy max="100"/>
+ </RollingFile>
+ </Appenders>
+
+ <Loggers>
+ <Logger name="scb-trace" level="INFO" additivity="false">
+ <AppenderRef ref="TraceLog"/>
+ </Logger>
+ <Logger name="scb-metrics" level="INFO" additivity="false">
+ <AppenderRef ref="MetricsLog"/>
+ </Logger>
+
+ <Root level="INFO">
+ <AppenderRef ref="Console"/>
+ <AppenderRef ref="RootLog"/>
+ </Root>
+ </Loggers>
+</Configuration>
+```
+
+每个微服务都集成和实现`可观测API`。
+
+```java
+@Path("/v1/scb/observability")
+public interface ObservabilityService {
+ String NAME = "scb-observability";
+
+ @Path("/searchTrace")
+ @GET
+ SearchTraceResponse searchTrace(@NotNull @QueryParam("timestamp") String
timestamp,
+ @NotNull @QueryParam("traceId") String traceId);
+
+ @Path("/searchLog")
+ @GET
+ SearchLogResponse searchLog(@NotNull @QueryParam("timestamp") String
timestamp,
+ @NotNull @QueryParam("traceId") String traceId);
+
+ @Path("/downloadLog")
+ @GET
+ Part downloadLog(@NotNull @QueryParam("timestamp") String timestamp);
+
+ @Path("/downloadMetrics")
+ @GET
+ Part downloadMetrics(@NotNull @QueryParam("timestamp") String timestamp);
+}
+```
+
+最后,我们可以开发一个管理控制服务,实现`管理面可观测API`, 就完成了可观测能力的构建:
+
+```java
+@Path("/v1/scb/admin/observability")
+public interface AdminObservabilityService {
+ String NAME = "scb-admin-observability";
+
+ @Path("/searchTrace")
+ @GET
+ List<SearchTraceResponse> searchTrace(@NotNull @QueryParam("timestamp")
String timestamp,
+ @NotNull @QueryParam("traceId") String traceId);
+
+ @Path("/searchLog")
+ @GET
+ List<SearchLogResponse> searchLog(@NotNull @QueryParam("timestamp") String
timestamp,
+ @NotNull @QueryParam("traceId") String traceId);
+
+ @Path("/downloadLog")
+ @GET
+ Part downloadLog(@NotNull @QueryParam("timestamp") String timestamp,
+ @NotNull @QueryParam("serviceName") String serviceName,
+ @NotNull @QueryParam("instanceId") String instanceId);
+
+ @Path("/downloadMetrics")
+ @GET
+ Part downloadMetrics(@NotNull @QueryParam("timestamp") String timestamp,
+ @NotNull @QueryParam("serviceName") String serviceName,
+ @NotNull @QueryParam("instanceId") String instanceId);
+}
+```
+
+## 和传统方案的对比分析
+
+与部署ELK、SkyWalking和Prometheus去采集数据的传统方案对比,上述方案非常简单和实用,能够帮助实时在线分析问题,该方案也无需将日志、调用链和指标等数据集中存储下来,可以节省大量的存储设备空间。
当然它的缺点也是显而易见的,对于已经下线的服务,或者对于历史问题需要追溯的情况,则采集不到相关的信息。
站在问题定位的角度,存储海量的日志、调用链和指标数据,大量数据都是和问题无关的,并且多数情况是要在第一时间完成问题定界和信息收集,因此上述方案相比于传统方案就有了非常大的竞争力优势。
+
+>
客户故事:很多客户花了大量成本构建可观测能力,依然无法指导运维人员快速定界和定位问题。通过建立一个简单实用的问题定界流程和采集数据的手段,可以帮助提升问题定位效率。
+
diff --git
a/java-chassis-reference/zh_CN/docs/best-practise/design-resilience.md
b/java-chassis-reference/zh_CN/docs/best-practise/design-resilience.md
new file mode 100644
index 0000000..768e2ff
--- /dev/null
+++ b/java-chassis-reference/zh_CN/docs/best-practise/design-resilience.md
@@ -0,0 +1,72 @@
+# 韧性架构设计
+
+架构设计的目的是解决软件系统复杂性带来的问题。简单描述为如下几个业务目标:
+
+*
业务变化不需要改变架构。新增业务、修改业务或者删除业务,不需要调整架构。这样业务团队能够专注于业务开发和运营,降低技术难度,提升开发效率。同时满足业务创新对于试错的诉求,快速创建新的业务模块,快速丢弃被验证不合理的业务,降低创新成本,也不至于对稳定业务造成影响。
+*
适应业务增长对于性能的要求。用户增长、营收增长、业务增长以及使用场景变化,不需要调整架构,能够快速适应。比如通过资源投入的线性增长,就能快速满足用户增长的需要,不需要修改架构和代码,这样业务团队可以聚焦于业务优化,从而以更加低的资源投入,满足更大的用户增长需求。
+*
可持续演进的目标。架构设计需要充分考虑持续演进的目标,能够阶段性适应业务的需要,并能够分阶段进行优化。架构设计目标应该尽可能兼顾遗留系统的演进,降低频繁推倒重来的风险,分阶段优化、验证和反馈,控制好投入的成本和产出的效益。
+
+除了业务目标,架构设计还会关注其他的技术目标,比如安全、隐私、DFx等。架构设计也不得不面对一个现实问题:通常只能根据架构师的经验设计一个架构,并且回答这个架构是如何解决上述业务目标的,因此架构设计是从当前已有的方案中寻找到最合适的方案的过程,是一个证实和证伪的过程,并不是一个重新创造的过程。微服务架构就是当前最好的解决上述目标的一个选择。后面用“韧性架构”来表达上述设计目标,分析Fence项目在一些具体的场景下如何满足“韧性架构”的设计要求。
+
+开始之前,回顾下Fence项目的主要部件组成:
+
+
+
+## 应对业务变化
+业务变化主要指功能的增、删、改,在微服务架构下,表现为REST接口的调整、微服务的拆分。Fence项目通过引入微服务网关来屏蔽业务变化对最终用户的影响。
+
+应用网关提供灵活的路由配置以及灰度发布能力,满足业务组件独立部署升级、拆分合并等持续业务变化对功能设计、持续部署带来的挑战。
+
+```yaml
+servicecomb:
+ http:
+ dispatcher:
+ edge:
+ ## 后端服务
+ url:
+ enabled: true
+ pattern: "/api/(.*)"
+ mappings:
+ resource-server:
+ prefixSegmentCount: 2
+ path: "/api/resource/.*"
+ microserviceName: resource-server
+ authentication-server:
+ prefixSegmentCount: 2
+ path: "/api/authentication/.*"
+ microserviceName: authentication-server
+ admin-service:
+ prefixSegmentCount: 2
+ path: "/api/admin/.*"
+ microserviceName: admin-service
+ ## 前端服务
+ http:
+ enabled: true
+ pattern: "/ui/(.*)"
+ mappings:
+ admin-website:
+ prefixSegmentCount: 0
+ path: "/ui/admin/.*"
+ microserviceName: admin-website
+```
+
+
+
+## 适应业务增长
+业务增长技术上表现为处理能力的增长。应用网关和微服务钧采用无状态设计,使得他们都可以通过增加实例来满足更大的业务处理需求,而不需要依赖于持续的硬件升级,可以用更廉价的硬件来处理更大的业务流量。网关的认证优先采用JWT
Token机制,每次请求的认证都在一个实例上处理,避免依赖于数据库、Redis等中间件带来的锁竞争。
+
+应用网关的多协议支持给性能调优也带来了很大的方便,应用网关支持REST协议自动转换HIGHWAY协议,在处理能力满足业务需要的时候,内部服务采用REST协议,以增加可靠性、满足兼容性、提升可维护性等需要。在特别需要高性能的情况下,可以将整个微服务,或者部分耗时的接口设置为HIGHWAY协议。
+
+业务增长也会带来组织的调整,从而带来系统边界的变化。在系统边界,需要设计不同的认证鉴权机制和交互机制,还需要避免中间件管理规模变大,比如注册中心,造成全局性的故障。
+
+
+
+## 持续演进目标
+持续演进包括增加微服务、遗留系统、技术创新等几个场景。
+
+在使用微服架构的时候,需要保证遗留系统资产能够被继承,避免重复造轮子,但也需要避免遗留系统重构、甚至重写带来的工作负荷。
+
+技术创新需要在现有技术之上,引入新的技术,比如新的语言、新的框架,需要确保这些系统之间能够更好的协作。
+
+
+
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/design-security.md
b/java-chassis-reference/zh_CN/docs/best-practise/design-security.md
new file mode 100644
index 0000000..d1395da
--- /dev/null
+++ b/java-chassis-reference/zh_CN/docs/best-practise/design-security.md
@@ -0,0 +1,268 @@
+# 安全认证设计
+
+ServiceComb Fence 鉴权实现的主要框架参考了 [The OAuth 2.0 Authorization
Framework](https://tools.ietf.org/html/rfc6749) 和 [OpenID
Connect](https://openid.net/connect/) 。 项目参考 [Spring
Security](https://spring.io/projects/spring-security) 给开发者提供了接口。
+
+## 认证流程图
+
+
+
+
+## 鉴权流程图
+
+
+
+## 认证鉴权流程介绍
+
+### 密码模式
+
+* Client 输入用户名密码向 Authentication Server 请求 Token。
+
+```
+** HTTP Request **
+
+POST http://localhost:9090/v1/token HTTP/1.1
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=password&username=admin&password=changeMyPassword
+
+** HTTP Response **
+
+{
+ "token_type": "bearer",
+ "access_token": "SlAV32hkKG",
+ "refresh_token": "8xLOxBtZp8",
+ "id_token": "eyJ...hbGciOiJSU...zI1NiIsImtpZCI6Ij",
+ "expires_in": 600,
+ "scope": null,
+ "additionalInformation": null
+}
+```
+
+* Authentication Server 发送 Token 给 Client 。
+
+* Client 携带 ID Token 请求 Edge Service 。
+
+```
+** HTTP Request **
+
+POST
http://localhost:9090/api/resource-server/v1/auth/handler/adminSayHello?name=Hi
HTTP/1.1
+Content-Type: application/x-www-form-urlencoded
+Authorization: Bearer eyJ...hbGciOiJSU...zI1NiIsImtpZCI6Ij
+```
+
+* Edge Service 将 ID Token 转发给Resource Server。
+* Resource Server 返回对应的资源给 Client 。
+
+## 配置 Authentication Server
+
+Authentication Server 主要提供认证和授权等接口。
+
+```java
+@Configuration
+public class AuthenticationConfiguration {
+ @Bean(name = CommonConstants.BEAN_AUTH_PASSWORD_ENCODER)
+ public PasswordEncoder authPasswordEncoder() {
+ return Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
+ }
+
+ @Bean(name = {CommonConstants.BEAN_AUTH_SIGNER,
CommonConstants.BEAN_AUTH_SIGNATURE_VERIFIER})
+ public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier
separately.
+ // If using MacSigner, need to protect the shared key by properly
encryption.
+ return new MacSigner("Please change this key.");
+ }
+
+ @Bean(name = {CommonConstants.BEAN_AUTH_ID_TOKEN_STORE})
+ public JWTTokenStore jwtTokenStore(@Autowired
@Qualifier(CommonConstants.BEAN_AUTH_SIGNER) Signer signer,
+ @Autowired @Qualifier(CommonConstants.BEAN_AUTH_SIGNATURE_VERIFIER)
SignerVerifier signerVerifier) {
+ return new JWTTokenStoreImpl(signer, signerVerifier);
+ }
+
+ @Bean(name = {CommonConstants.BEAN_AUTH_ACCESS_TOKEN_STORE,
+ CommonConstants.BEAN_AUTH_REFRESH_TOKEN_STORE})
+ public SessionTokenStore sessionTokenStore() {
+ return new SessionTokenStore();
+ }
+}
+```
+
+* UserDetailsManager
+
+获取用户详情,包括用户名称、角色等信息。包括 InMemoryUserDetailsManager 、 JDBCUserDetailsManager
等实现。JDBCUserDetailsManager。
+
+* Signer 和 SignatureVerifier
+
+生成 Token 和对 Token 进行校验。Singer 和 SignatureVerifier 是配套使用的, 在 Authentication
Server , 生成 Token 的时候,需要使用 Singer 。 验证 Token 的有效性 (比如查询 userDetails 等场景), 需要使用
SignatureVerifier 。 通常有两种方式进行签名和校验, 一种是基于对称秘钥的机制,比如MacSigner,即是 Singer, 也是
SignatureVerifier (SignerVerifier); 一种是基于非对称秘钥的机制, 比如 RsaSigner 和 RsaVerifier
, 生成 Token 和校验 Token 的秘钥是不同的。
+
+* AbstractOpenIDTokenStore
+ 在Authentication Server,TokenStore主要用来生成Access Token, Refresh Token和ID Token,
默认情况下, Access Token和Refresh
Token都使用AbstractSessionIDTokenStore(本例子使用了InMemoryOpenIDTokenStore,业务代码通常需要换为JDBC、Redis等实现),
ID Token使用JWTTokenStore。 JWTTokenStore是一个无状态的会话机制,Authentication
Server的任何一个实例都可以独立生成。支持Refresh Token认证的场景下,还需要实现通过Refresh Token读取其他信息的方法。
+
+* PasswordEncoder
+
+从 UserDetailsService 校验用户密码的时候需要使用。 开发者需要在加密性能和保密程度方面选择合适的算法。 常用的有
Pbkdf2PasswordEncoder , 它可以设置迭代次数,能够更好的保护密码不被暴力破解。
+
+## 配置 Resource Server
+
+Resource Server 对 Client 的访问进行认证, 并进行权限控制。
+
+Resource Server 需要配置 Signer、SignerVerifier、TokenStore 等, 对用户会话进行认证。
+
+```java
+@Configuration
+@EnableMethodSecurity
+public class AuthenticationConfiguration {
+ @Bean(name = {CommonConstants.BEAN_AUTH_SIGNER,
CommonConstants.BEAN_AUTH_SIGNATURE_VERIFIER})
+ public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier
separately.
+ // If using MacSigner, need to protect the shared key by properly
encryption.
+ return new MacSigner("Please change this key.");
+ }
+
+ @Bean(name = CommonConstants.BEAN_AUTH_ID_TOKEN_STORE)
+ public JWTTokenStore authIDTokenStore(@Autowired
@Qualifier(CommonConstants.BEAN_AUTH_SIGNER) Signer signer,
+ @Autowired @Qualifier(CommonConstants.BEAN_AUTH_SIGNATURE_VERIFIER)
SignerVerifier signerVerifier) {
+ return new JWTTokenStoreImpl(signer, signerVerifier);
+ }
+
+ @Bean
+ public AuthenticationProviderFilter authenticationProviderFilter() {
+ return new AuthenticationProviderFilter();
+ }
+
+ @Bean
+ public GrantedAuthorityDefaults grantedAuthorityDefaults() {
+ return new GrantedAuthorityDefaults("");
+ }
+
+ @Bean
+ @Order(0)
+ public AuthenticationAuthFilter authenticationAuthFilter() {
+ return new AuthenticationAuthFilter();
+ }
+
+ @Bean
+ @Order(100)
+ public ConfigBasedAuthorizationAuthFilter
configBasedAuthorizationAuthFilter() {
+ return new ConfigBasedAuthorizationAuthFilter();
+ }
+}
+
+```
+
+* Signer、SignatureVerifier
+ 对Token进行校验需要,实际上Resource Server只需要使用SignatureVerifier。
+
+* JWTTokenStore
+ Edge Service将ID Token传递给Resource
Server,所以只需要配置JWTTokenStore。基于会话认证的场景,需要提供AbstractOpenIDTokenStore。
+
+
+* 权限配置
+
+fence 提供了两种方式进行权限配置。 一种是基于配置文件的,一种是基于 Annotation 。
+
+基于文件的配置, 在 microservice.yaml 中可以配置每个方法的访问权限。
+
+```
+servicecomb:
+ authencation:
+ access:
+ needAuth: true
+ HandlerAuthEndpoint:
+ adminSayHello:
+ roles: ADMIN
+ guestSayHello:
+ roles: GUEST
+ guestOrAdminSayHello:
+ roles: ADMIN,GUEST
+ # everyoneSayHello: all can
+```
+
+还可以统一配置Schema
+
+```
+servicecomb:
+ authencation:
+ access:
+ needAuth: true
+ roles:
+ HandlerAuthEndpoint: ADMIN
+```
+
+或者所有
+
+```
+servicecomb:
+ authencation:
+ access:
+ needAuth: true
+ roles: ADMIN
+```
+
+基于 Annotation , 可以使用 PreAuthorize 标签
+
+```
+@PreAuthorize("hasRole('ADMIN')")
+```
+
+Annotation 支持默认没有启用, 可以通过 EnableGlobalMethodSecurity 标签启用。
+
+```
+@Configuration
+@EnableGlobalMethodSecurity(
+ prePostEnabled = true)
+public class MethodSecurityConfiguration extends
GlobalMethodSecurityConfiguration {
+ @Override
+ protected MethodSecurityExpressionHandler createExpressionHandler() {
+ DefaultMethodSecurityExpressionHandler h =
(DefaultMethodSecurityExpressionHandler) super.createExpressionHandler();
+ h.setDefaultRolePrefix("");
+ return h;
+ }
+}
+```
+
+
+## 配置 Edge Service
+
+Edge Service 是微服务接入层。 接入层在认证鉴权的功能包括透传 Authentication Server的请求,
对Token进行认证,控制内部接口和外部接口的隔离等功能。
+
+Edge Service 需要配置 JWTTokenStore 等, 对用户会话进行认证。Edge Service 从HTTP头里面读取Id Token,
然后通过 JWTTokenStore检查ID Token是否有效,如果有效,将对应的 ID Token传递到 Resource Server。
在基于会话认证的场景下,需要使用 SessionTokenStore。
+
+```
+@Configuration
+public class AuthenticationConfiguration {
+ @Bean(name = {CommonConstants.BEAN_AUTH_SIGNER,
CommonConstants.BEAN_AUTH_SIGNATURE_VERIFIER})
+ public SignerVerifier authSignerVerifier() {
+ // If using RSA, need to configure authSigner and authSignatureVerifier
separately.
+ // If using MacSigner, need to protect the shared key by properly
encryption.
+ return new MacSigner("Please change this key.");
+ }
+
+ @Bean(name = CommonConstants.BEAN_AUTH_ID_TOKEN_STORE)
+ public JWTTokenStore authIDTokenStore(@Autowired
@Qualifier(CommonConstants.BEAN_AUTH_SIGNER) Signer signer,
+ @Autowired @Qualifier(CommonConstants.BEAN_AUTH_SIGNATURE_VERIFIER)
SignerVerifier signerVerifier) {
+ return new JWTTokenStoreImpl(signer, signerVerifier);
+ }
+
+ @Bean(name = CommonConstants.BEAN_AUTH_OPEN_ID_TOKEN_STORE)
+ public EdgeOpenIDTokenStore edgeOpenIDTokenStore() {
+ return new EdgeOpenIDTokenStore();
+ }
+
+ @Bean(name = {CommonConstants.BEAN_AUTH_ACCESS_TOKEN_STORE,
+ CommonConstants.BEAN_AUTH_REFRESH_TOKEN_STORE})
+ public SessionTokenStore sessionTokenStore() {
+ return new SessionTokenStore();
+ }
+
+ @Bean
+ public AuthenticationEdgeFilter authenticationEdgeFilter() {
+ return new AuthenticationEdgeFilter();
+ }
+
+ @Bean
+ public InternalAccessEdgeFilter internalAccessEdgeFilter() {
+ return new InternalAccessEdgeFilter();
+ }
+}
+```
+
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/fence-deploy.png
b/java-chassis-reference/zh_CN/docs/best-practise/fence-deploy.png
new file mode 100644
index 0000000..dcd8a49
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/fence-deploy.png differ
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/fence-home.png
b/java-chassis-reference/zh_CN/docs/best-practise/fence-home.png
new file mode 100644
index 0000000..3c0d4bd
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/fence-home.png differ
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/observability.png
b/java-chassis-reference/zh_CN/docs/best-practise/observability.png
new file mode 100644
index 0000000..dc3578d
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/observability.png differ
diff --git
a/java-chassis-reference/zh_CN/docs/best-practise/resilience-change.png
b/java-chassis-reference/zh_CN/docs/best-practise/resilience-change.png
new file mode 100644
index 0000000..191e69d
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/resilience-change.png differ
diff --git
a/java-chassis-reference/zh_CN/docs/best-practise/resilience-growth.png
b/java-chassis-reference/zh_CN/docs/best-practise/resilience-growth.png
new file mode 100644
index 0000000..7df8538
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/resilience-growth.png differ
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/resilience-new.png
b/java-chassis-reference/zh_CN/docs/best-practise/resilience-new.png
new file mode 100644
index 0000000..bd23816
Binary files /dev/null and
b/java-chassis-reference/zh_CN/docs/best-practise/resilience-new.png differ
diff --git a/java-chassis-reference/zh_CN/docs/best-practise/scaffolding.md
b/java-chassis-reference/zh_CN/docs/best-practise/scaffolding.md
new file mode 100644
index 0000000..b44c4ae
--- /dev/null
+++ b/java-chassis-reference/zh_CN/docs/best-practise/scaffolding.md
@@ -0,0 +1,19 @@
+# 项目脚手架
+
+为了支持快速开发,提供脚手架快速生成项目是非常好的实践。ServiceComb Fence的网关服务(edge
service)、认证服务(authentication
server)、管理服务(admin-service、admin-website),开发者可以直接基于源码扩展新的业务场景和逻辑。一般的业务服务,都是基于资源服务(resource-server)模板。
+
+编译完成 ServiceComb Fence 项目后,可以使用 maven archetype 来生成一个新的微服务项目:
+
+
+```shell
+mvn archetype:generate
+ -DserviceName=resource-server2
+ -DartifactId=resouerce-server2
+ -DwebRoot=resource
+ -DserverPort=9090
+ -DarchetypeGroupId=org.apache.servicecomb.fence
+ -DarchetypeArtifactId=fence-archetype
+```
+
+基于可运行的项目工程完成一个新的业务开发,可以快速迭代新功能,并且可以在此基础上不断的补充新的测试用例,以支持系统的持续演进,是非常好的软件工程实践。
+
diff --git a/java-chassis-reference/zh_CN/mkdocs.yml
b/java-chassis-reference/zh_CN/mkdocs.yml
index 5967d57..2f9bd58 100644
--- a/java-chassis-reference/zh_CN/mkdocs.yml
+++ b/java-chassis-reference/zh_CN/mkdocs.yml
@@ -105,20 +105,26 @@ nav:
- 兼容问题和兼容性策略: featured-topics/compatibility.md
- 性能问题分析和调优: featured-topics/performance.md
- 技术解密:
- - Java Chassis 3技术解密:负载均衡选择器: secrets/load-balancer.md
- - Java Chassis 3技术解密:注册中心分区隔离: secrets/zone-isolation.md
- - Java Chassis 3技术解密:多种序列化方式支持: secrets/serialization.md
- - Java Chassis 3技术解密:熔断机制的改进路程: secrets/circuit-breaker.md
- - Java Chassis 3技术解密:过载状态下的快速失败: secrets/fail-fast.md
- - Java Chassis 3技术解密:应用视角的配置管理: secrets/applied-config.md
- - Java Chassis 3技术解密:易扩展的多种注册中心支持: secrets/registries.md
- - Java Chassis 3技术解密:与Spring Cloud的互操作: secrets/interoperability.md
- - Java Chassis 3技术解密:ZooKeeper注册和配置中心: secrets/zookeeper.md
- - Java Chassis 3技术解密:契约优先(API First)开发: secrets/api-first.md
- - Java Chassis 3技术解密:接口维度负载均衡: secrets/load-balancer-operation.md
- - Java Chassis 3技术解密:实用的可观测性: secrets/observability.md
- - Java Chassis 3技术解密:流式响应和人工智能应用开发: secrets/sse.md
- - Java Chassis 3技术解密:WebSocket和人工智能应用开发: secrets/websocket.md
+ - 负载均衡选择器: secrets/load-balancer.md
+ - 注册中心分区隔离: secrets/zone-isolation.md
+ - 多种序列化方式支持: secrets/serialization.md
+ - 熔断机制的改进路程: secrets/circuit-breaker.md
+ - 过载状态下的快速失败: secrets/fail-fast.md
+ - 应用视角的配置管理: secrets/applied-config.md
+ - 易扩展的多种注册中心支持: secrets/registries.md
+ - 与Spring Cloud的互操作: secrets/interoperability.md
+ - ZooKeeper注册和配置中心: secrets/zookeeper.md
+ - 契约优先(API First)开发: secrets/api-first.md
+ - 接口维度负载均衡: secrets/load-balancer-operation.md
+ - 实用的可观测性: secrets/observability.md
+ - 流式响应和人工智能应用开发: secrets/sse.md
+ - WebSocket和人工智能应用开发: secrets/websocket.md
+- 最佳实践:
+ - Fence项目介绍: best-practise/about-fence.md
+ - 韧性架构设计: best-practise/design-resilience.md
+ - 安全认证设计: best-practise/design-security.md
+ - 可观测性设计: best-practise/design-observability.md
+ - 项目脚手架: best-practise/scaffolding.md
- 升级指导:
- 1.3.0 升级 2.0.0指导: upgrading/1_3_0T2_0_0.md
- 2.0.0 升级 2.0.1指导: upgrading/2_0_0T2_0_1.md