Dubbo 生态添新兵,Dubbo Admin 发布 v0.1
为了提升 Dubbo 里程碑版本2.7.0的使用体验,我们于去年年中启动了 Dubbo Admin 的重构计划,并作为Dubbo生态的子项目,于近期发布了v0.1,重构后的项目在结构上的变化如下:
将后端框架从webx替换成spring boot
前端采用Vue和Vuetify.js作为开发框架
移除velocity模板
集成swagger,提供api管理功能
当前版本的Dubbo Admin包含了之前版本中的绝大部分功能,包括服务治理,服务查询等,同时支持了Dubbo2.7中服务治理的新特性。
配置规范
由于在Dubbo2.7中,配置中心和注册中心做了分离,并且增加了元数据中心,因此Dubbo Admin的配置方式也做了更新,application.properties中的配置如下:
admin.registry.address=zookeeper://127.0.0.1:2181
admin.config-center=zookeeper://127.0.0.1:2181
admin.metadata.address=zookeeper://127.0.0.1:2181
也可以和Dubbo2.7一样,在配置中心指定元数据和注册中心的地址,以zookeeper为例,配置的路径和内容如下:
# /dubbo/config/dubbo/dubbo.properties
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
配置中心里的地址会覆盖掉本地application.properties的配置
功能介绍
功能上,主要延续了之前版本的功能,包括服务查询和服务治理,2.7版本在服务治理的功能上有了很大的改进,这些改进也大部分都会以Dubbo Admin作为入口来体现。
标签路由
标签路由是Dubbo2.7引入的新功能,配置以应用作为维度,给不同的服务器打上不同名字的标签,配置如下图所示:
1548675129621_1f2f3f68_4f35_4105_97e2_c4a0d7dc62c8_jpeg
调用的时候,客户端可以通过setAttachment的方式,来设置不同的标签名称,比如本例中,setAttachment(tag1),客户端的选址范围就在如图所示的三台机器中,可以通过这种方式来实现流量隔离,灰度发布等功能。
应用级别的服务治理
在Dubbo2.6及更早版本中,所有的服务治理规则都只针对服务粒度,如果要把某条规则作用到应用粒度上,需要为应用下的所有服务配合相同的规则,变更,删除的时候也需要对应的操作,这样的操作很不友好,因此Dubbo2.7版本中增加了应用粒度的服务治理操作,对于条件路由(包括黑白名单),动态配置(包括权重,负载均衡)都可以做应用级别的配置:
1548675095660_2abe00e4_7a3c_4c49_8649_0cc81e00e324_jpeg
上图是条件路由的配置,可以按照应用名,服务名两个维度来填写,也可以按照这两个维度来查询。
1548675169501_57b22613_ba3a_462b_b3ba_af34ea778589_jpeg
条件路由,标签路由和动态配置都采用了yaml格式的文本编写,其他的规则配置还是采用了表单的形式。
关于兼容性
Dubbo2.6到Dubbo2.7,服务治理发生了比较大的变化,Dubbo Admin兼容两个版本的用法:
对于服务级别的配置,会按照Dubbo2.6(URL)和Dubbo2.7(配置文件)两种格式进行写入,保证Dubbo2.6的客户端能够正确读取,解析规则
对于应用级别的配置,包括标签路由,只会按照Dubbo2.7的格式进行写入,因为Dubbo2.6无此功能,不需要做向前兼容。
Dubbo Admin只会按照Dubbo2.7的格式进行配置读取,因此,所有在Dubbo Admin上做的配置都可以被读到,但是之前遗留的,Dubbo2.6格式的URL无法被读取。
对于同一个应用或者服务,每种规则只能够配置一条,否则新的会覆盖旧的。
配置管理
配置管理也是配合Dubbo2.7新增的功能,在Dubbo2.7中,增加了全局和应用维度的配置。
全局配置:
1548675196442_4611bfd9_5077_4bd2_a2b1_ad89c5eefc13_jpeg
全局配置里可以指定注册中心,元数据中心的地址,服务端和客户端的超时时间等,这些配置在全局内生效。除了配置写入,也可以用来查看。如果使用zookeeper作为注册中心和元数据中心,还可以看到配置文件所在位置的目录结构。
应用和服务配置
1548675223170_772fd97b_f49f_4cf6_be40_34355f8159a1_jpeg
应用级别的配置可以为应用或者应用内的服务指定配置,在服务维度上,需要区分提供者和消费者。dubbo.reference.{serviceName}表示作为该服务消费者的配置,dubbo.provider.{servcieName}表示作为该服务提供者的配置。优先级服务 > 应用 > 全局。其中注册中心和元数据中心的地址,只能在全局配置中指定,这也是Dubbo2.7中推荐的使用方式。
元数据和服务测试
元数据是Dubbo2.7中新引入的元素,主要的使用场景就在Dubbo Admin中,主要体现在两个地方:
服务详情展示:
1548675234502_67cefa2f_e180_4715_a203_a98bf515fe4f_jpeg
跟之前版本相比,Dubbo2.7中增加了对服务方法完整签名的记录,因此服务详情中也增加了方法信息的详情,可以看到方法名,方法参数列表以及返回值信息。
服务测试:
1548675056214_730b7a7b_d4af_4a57_ab3f_380c5afcdabb_jpeg
更重要的,元数据为服务测试提供了数据基础,可以在页面上调用真实的服务提供者,方便测试,也不需要为了调用服务去搭建一套Dubbo环境以及编写消费端代码。服务测试的详细使用方式可通过点击这里进行了解。
添加 SessionController 用于用户登录,内容如下:
using System.ComponentModel.DataAnnotations;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Mvc;
namespace ServiceA.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SessionController : ControllerBase
{
public async Task<string> Login(UserRequestModel userRequestModel)
{
// discover endpoints from metadata
var client = new HttpClient();
DiscoveryResponse disco = await client.GetDiscoveryDocumentAsync("http://127.0.0.1:8021");
if (disco.IsError)
{
return "认证服务器未启动";
}
TokenResponse tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "ServiceAClient",
ClientSecret =dasheng178.com "ServiceAClient",
UserName = userRequestModel.Name,
Password = userRequestModel.Password
});
return tokenResponse.IsError ? tokenResponse.Error : tokenResponse.AccessToken;
}
}
public class UserRequestModel
{
[Required(ErrorMessage = "用户名称不可以为空")]
public string Name {www.078886.cn get; set; }
[Required(ErrorMessage = "用户密码不可以为空")]
public string Password { get; set; }
}
}
添加 HealthController 用于 Consul 进行服务健康检查,内容如下:
using Microsoft.AspNetCore.Mvc;
namespace ServiceA.Controllers
{
[Route("api/[controller]"), ApiController]
public class HealthController : ControllerBase
{
/// <summary>
/// 健康检查
/// </summary>
/// <returns>www.yongshiyule178.com</returns>
[HttpGet]
public IActionResult Get()
{
return Ok();
}
}
}
更改 ValuesController.cs 内容如下:
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace ServiceA.Controllers
{
[Authorize] //添加 Authorize Attribute 以使该控制器启用认证
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new[] { "value1", "value2" };
}
}
}
注意,以上基本完成了 ServiceA 的服务构建,但在实际应用中应做一些修改,例如:IdentityServer 地址应在 appsettings.json 中进行配置,不应把地址分散于项目中各处;认证服务启用最好在全局启用,以防止漏写等等。ServiceB 的内容与 ServiceA 大致相似,因此文章中将不再展示 ServiceB 的构建过程。
Gateway 构建
添加ASP.Net Web
添加空项目
打开程序包管理器控制台输入命令:
csharp install-package Ocelot //添加 Ocelot
csharp install-package Ocelot.Provider.Consul // 添加 Consul 服务发现
添加 ocelot.json 文件,内容如下
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/ServiceA/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"ServiceName": "ServiceA", //consul 服务中 ServiceA 的名称
"LoadBalancerOptions": {
"Type": "LeastConnection"
}
},
{
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/ServiceB/{everything}",
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"ServiceName": "ServiceB", //consul 服务中 ServiceB 的名称
"LoadBalancerOptions": {
"Type": "LeastConnection"
}
}
],
"GlobalConfiguration": {
"ServiceDiscoveryProvider": { // Consul 服务发现配置
"Host": "localhost", // Consul 地址
"Port": 8500,
"Type": "Consul"
}
}
}
删除 StartUp.cs 文件,在 Program.cs 文件中添加如下内容
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Consul;
namespace ApiGateway
{
public class Program
{
public static void Main(string[] args)
{
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.www.ouyi3pt1.cn{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile(www.dituyule.org"ocelot.json")
.AddEnvironmentVariables(www.yingxionghui1.cn);
})
.ConfigureServices(services =>
{
services.AddOcelot().AddConsul();
})
.ConfigureLogging((hostingContext, logging) =>
{
//add your logging
})
.UseIISIntegration()
.Configure(app =>
{
app.UseOcelot().Wait();
})
.Build()
.Run();
}
}
}
注意:打开 Gateway.csproj 文件,更改
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
为
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>www.fengshen157.com/ OutOfProcess</AspNetCoreHostingModel>
</PropertyGroup>
至此,一个基础网关基本构建完成。
构建 Consul 服务
使用 Chocoletey 安装 Consul,
choco install consul
新建一个文件夹以保存 Consul 服务配置
在 consul.d 文件夹中添加配置文件,内容如下:
{
"services": [{
"ID": "ServiceA",
"Name": "ServiceA",
"Tags": [
"ServiceAWebApi", "Api"
],
"Address": "127.0.0.1",
"Port": 8010,
"Check": {
"HTTP": "http://127.0.0.1:8010/Api/health",
"Interval": "10s"
}
}, {
"id": "ServiceB",
"name": "ServiceB",
"tags": [
"ServiceBWebApi","Api"
],
"Address": "127.0.0.1",
"Port": 8011,
"Check": [{
"HTTP": "http://127.0.0.1:8011/Api/health",
"Interval": "10s"
}
]
}
]
}
启动 consul 服务
consul agent -dev -config-dir=./consul.d
启动后在浏览器中输入 http://localhost:8500/ui/ 以查看Consul服务
Postman 验证
F5 启动 Gateway 项目,启动 Postman 发送请求到 ServiceA 获取 Token。
使用 Token 请求 ServiceA Values 接口
当尝试使用 ServiceA 获取到的 Token 去获取 ServiceB 的数据时,请求也如意料之中返回 401
总结
至此,一个由 .NET Core、IdentityServer4、Ocelot、Consul实现的基础架构搭建完毕。源码地址
Dubbo 生态添新兵,Dubbo Admin 发布 v0.1的更多相关文章
- dubbo源码之四——dubbo服务发布
dubbo版本:2.5.4 服务发布是服务提供方向注册中心注册服务过程,以便服务消费者从注册中心查阅并调用服务. 服务发布方在spring的配置文件中配置如下: <bean id="d ...
- dubbo 源码学习1 服务发布机制
1.源码版本:2.6.1 源码demo中采用的是xml式的发布方式,在dubbo的 DubboNamespaceHandler 中定义了Spring Framework 的扩展标签,即 <dub ...
- Dubbo 系列(05-1)服务发布
目录 Dubbo 系列(05-1)服务发布 Spring Cloud Alibaba 系列目录 - Dubbo 篇 1. 背景介绍 1.1 服务暴露整体机制 2. 源码分析 2.1 前置工作 2.2 ...
- Spring Cloud Alibaba生态探索:Dubbo、Nacos及Sentinel的完美结合
@ 目录 背景 一.项目框架 1.1 采用IDEA和Maven多模块进行项目搭建 1.2 模块管理及版本管理 二.微服务公共接口 2.1 定义一个公共接口Api 2.2 pom.xml 2.3 Goo ...
- dubbo系列五、dubbo核心配置
一.配置文件 1.生产者配置provider.xml <?xml version="1.0" encoding="UTF-8"?> <bean ...
- dubbo系列四、dubbo服务暴露过程源码解析
一.代码准备 1.示例代码 参考dubbo系列二.dubbo+zookeeper+dubboadmin分布式服务框架搭建(windows平台) 2.简单了解下spring自定义标签 https://w ...
- dubbo系列二、dubbo+zookeeper+dubboadmin分布式服务框架搭建(windows平台)
一.zookeeper配置中心安装 1.下载安装包,zookeeper-3.4.6.tar.gz 2.解压安装包,修改配置文件 参考zookeeper-3.4.6/conf/zoo_sample.cf ...
- dubbo入门学习(二)-----dubbo hello world
一.dubbo hello world入门示例 1.提出需求 某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址: 我们现在需要创建两个服务模块进行测试: 模块 功能 订单服务web模块 创 ...
- dubbo系列一、dubbo启动流程
目录 dubbo启动流程分析记录 一.dubbo provider启动流程 1.自动装配 2.ServiceBean处理 3.服务暴露export() 3.1.检测dubbo.xxx.配置属性,配置到 ...
随机推荐
- timestamp 字段
项目中由于需求设计,数据库中需要一个timestamp时间戳类型的字段来作为区别数据添加和修改的标识.由于timestamp在SQL SERVER 2005数据库中,不可为空的timestamp类型在 ...
- C/C++函数调用方式
__cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以 ...
- OO——电梯作业总结
目录 电梯作业总结 程序结构与复杂度的分析 第一次作业 第二次作业 第三次作业 程序BUG的分析 互测 自动评测 有效性 总结 电梯作业总结 程序结构与复杂度的分析 第一次作业 1.设计思路 第一次作 ...
- Tomcat 动态数据库连接池
package com.boguan.bte.util; import java.sql.Connection;import java.sql.SQLException;import java.uti ...
- 20155302《网络对抗》Exp9 Web安全基础
20155302<网络对抗>Exp9 Web安全基础 实验内容 本实践的目标理解常用网络攻击技术的基本原理.Webgoat实践下相关实验. 实验过程 1.webgoat的安装启动 使用自己 ...
- Linux 学习日记 2 (常用命令 + deb包的安装)
常用命令:以下是一些比较常用的命令,主要是关于安装软件的一些命令 @_@ cd ~/下载(文件名)/ //进入这个文件夹 , ~指的是根目录 cd .. //返回上一级文件夹 sudo apt-get ...
- xml中该使用属性还是元素
XML 中没有规定哪些必须放在属性或者子元素,因此使用哪种方式都是可以实现的.这取决于个人的经验和喜好.在可以使用元素也可以使用属性的两选一的情况下,个人更倾向于使用子元素.主要理由如下: 1. 属性 ...
- SSIS 你真的了解事务吗?
事务用于处理数据的一致性,事务的定义是,处于同一个事务中的操作是一个工作单元,要么全部执行成功,要么全部执行失败.把事务的概念应用到在实际的SSIS Package场景中,如何在Package中实现事 ...
- MQ见解
MQ 消息队列是系统级.模块级的通信.RPC是对象级.函数级通信. 1) 什么是推模式,什么是拉模式 2) 有没有消息丢失情况,如何防止 3) MQ用来解决什么问题 4) 你们用的什么MQ,为什么要用 ...
- Css_*^$
#search_condition [class*=search_submit] 表示class name里面的值包含search_submit $("#search_condition [ ...