YARP实现Dapr服务调用的反向代理
楔子
公司即将新开项目,打算用点时髦的技术,需要探探路。之前没做过微服务项目,没有技术栈方面的积(负)累(债),
干脆就上微软的分布式运行时Dapr......嗯......用来服务发现,然后等测试用的服务开发好了,就开始纠结用啥反向代理/网关,nginx都没怎么用过,更别提其他复杂网关了,这时看了一篇微软的YARP(Yet Another Reverse Proxy)的文章,发现已经preview.10了,还挺简单的,二次开发也方便,就用它先顶上吧。
开发环境
WSL
windows下跨平台开发的优秀方案,Linux 分发版我用的Ubuntu 20.04。Docker Desktop
虽然Docker不是Dapr开发环境的唯一选择,但Docker的跨平台做的很好,尤其Docker Desktop可视化,还自带Docker-Compose,安装也方便,可以弹射起步。
安装完打开后,打开控制台,验证一下:docker --version
dotnet SDK
YARP最低支持.NET Core 3.1,这个时间点(2021.04),推荐.NET 5。
验证:dotnet --version
Dapr
Dapr安装我记得挺快的,之后的初始化dapr init,网不好的话,可能要多试几次。
初始化确认Docker Desktop里dapr_placement,dapr_redis,dapr_zipkin 3个容器都在正常运行Tye
Tye 是微软开发提供的一款简化分布式应用开发的辅助命令行工具。用.NET写的,自带Dapr扩展。
dotnet tool全局安装后,可以如下验证:tye --version
知识储备
- Yarp配置
Yarp主要要配置的东西就是Cluster(集群)和ProxyRoute(路由),
本例中,ProxyRoute通过配置文件加载,Cluster指向Dapr-sidecar,由程序动态添加。
原理

- Yarp服务收到http请求
- 自定义Yarp转换:
http(s)://<Yarp服务>/api/<服务名>/XXXXX
转为
http://<Dapr-sidecar>/v1.0/invoke/<服务名>/method/XXXXX
注:这里的
<Dapr-sidecar>可能是动态的,因此不应该写死在配置文件里 - 请求转给Dapr-sidecar
- Dapr 服务发现 终端服务并调用
- 返回响应
开发
创建两个Asp.Net Core项目:
- GatewayDemo 网关Demo
- ServiceSample 示例服务
完成 ServiceSample
这个示例比较简单,所以不需要引用Dapr SDK,只需加一个测试用的Controller就好了:[Controller]
[Route("sample")]
public class SampleController
{
[HttpGet("{account}")]
public ActionResult Get(string account)
{
return new JsonResult(new
{
Account = account,
Balance = 100
});
}
}
添加引用
- GatewayDemo.csproj 增加包引用:
<PackageReference Include="Yarp.ReverseProxy" Version="1.0.0-preview.10.*" />注:Yarp.ReverseProxy从preview.10开始包名字变了,之前叫"Microsoft.ReverseProxy"。
- 这个示例比较简单,不需要引用Dapr的SDK
- GatewayDemo.csproj 增加包引用:
动态添加Yarp的Clusters自定义配置
public static IConfigurationBuilder AddDaprConfig(this IConfigurationBuilder configurationBuilder)
{
var httpEndpoint = DaprDefaults.GetDefaultHttpEndpoint(); //参考Dapr.Client,获取到dapr-sidecar的url
return configurationBuilder.AddInMemoryCollection(new[]
{
new KeyValuePair<string, string>("Yarp:Clusters:dapr-sidecar:Destinations:d1:Address", httpEndpoint),
});
}
//GatewayDemo的Program.cs
Host.CreateDefaultBuilder(args)
...
.ConfigureAppConfiguration((_, builder) => builder.AddDaprConfig())
GatewayDemo appsettings 增加Yarp相关配置
Yarp:
Routes:
- RouteId: r-module-master
ClusterId: dapr-sidecar
Match:
Path: api/service-sample/{**catch-all}
Metadata:
Dapr: method #标注Dapr
不用在意为什么是yaml,而不是json。
添加Yarp的自定义转换
public class DaprTransformProvider : ITransformProvider
{
public void ValidateRoute(TransformRouteValidationContext context)
{
} public void ValidateCluster(TransformClusterValidationContext context)
{
} public void Apply(TransformBuilderContext context)
{
string daprAct = null;
if (context.Route.Metadata?.TryGetValue(DaprYarpConst.MetaKeys.Dapr, out daprAct) ?? false) //通过元数据判断是否是Dapr服务,在配置文件中设置
{
switch (daprAct)
{
case DaprYarpConst.DaprAct.Method:
context.AddRequestTransform(transformContext =>
{
var index = transformContext.Path.Value!.IndexOf('/', 5); // format: /api/<服务>/xxxx
var appId = transformContext.Path.Value.Substring(5, index - 5);
var newPath = transformContext.Path.Value.Substring(index);
transformContext.ProxyRequest.RequestUri = new Uri($"{transformContext.DestinationPrefix}/v1.0/invoke/{appId}/method{newPath}");
return ValueTask.CompletedTask;
});
break;
}
}
}
} //GatewayDemo的Startup
public class Startup
{
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddReverseProxy()
.LoadFromConfig(_configuration.GetSection("Yarp"))
.AddTransforms<DaprTransformProvider>(); //加上自定义转换
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapReverseProxy();
//endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); });
});
}
}
配置tye
参考:name: dapr-yarp.sample
extensions:
- name: dapr
components-path: "./components/"
config: dapr-config
exclude-placement-container: true
placement-port: 6050
- name: zipkin
services:
- name: gateway-demo #服务名称最好不要有大写,容易出问题
project: ./GatewayDemo/GatewayDemo.csproj
- name: service-sample #服务名称最好不要有大写,容易出问题
project: ./ServiceSample/ServiceSample.csproj
- name: zipkin #dapr的追踪服务
external: true
bindings:
- name: http
port: 9411
ingress:
- name: ingress
rules:
- service: gateway-demo
path: /
bindings:
- name: ingress
protocol: https
port: 44363 #对外端口
./componnets/文件夹下还有一些配置文件,这里就不贴了
用tye同时运行多个项目
确保dapr那3个容器服务正常运行后,运行 tye run,通过tye的Dapr扩展,运行显示以下几个服务:- gateway-demo
- service-sample
- zipkin
- gateway-demo-dapr
- service-sample-dapr
- ingress
测试:
浏览器直接打开:https://localhost:44363/api/service-sample/sample/1234
如果显示{"account":"1234","balance":100}就说明通了。
附上Demo代码
尾声
因为目前没有用到对外的grpc调用和Actor、发布订阅等功能,所以本示例没有相关代码演示。
Yarp虽然还在preview,但有兴趣的.NET技术栈的玩家已经可以用它来做些简单的反向代理了。
YARP实现Dapr服务调用的反向代理的更多相关文章
- 生产环境中nginx既做web服务又做反向代理
一.写对于初入博客园的感想 众所周知,nginx是一个高性能的HTTP和反向代理服务器,在以前工作中要么实现http要么做反向代理或者负载均衡.尚未在同一台nginx或者集群上同时既实现HTTP又实现 ...
- Dubbo服务调用的动态代理和负载均衡
Dubbo服务调用的动态代理及负载均衡源码解析请参见:http://manzhizhen.iteye.com/blog/2314514
- 【Azure微服务 Service Fabric 】Service Fabric中应用开启外部访问端口及微服务之间通过反向代理端口访问问题
问题描述 1) 当成功的在Service Fabric集群中部署了应用后,如何来访问呢?如果是一个Web服务,它的URL又是什么呢? 2) 当Service Fabric集群中,服务之间如需要相互访问 ...
- Linux服务-配置Nginx反向代理
任务目标:实现基于轮询的方式调度三台web,并验证结果:实现基于权重的方式调度三台web,并验证结果:实现基于hash的方式调用三台web,并验证结果 由于刚刚做了nfs设置,为了提现实验结果,我在w ...
- docker学习(6) docker中搭建java服务及nginx反向代理
先看下容器规划: 上图中mysql容器的搭建见上篇博客,service1/2为java rest service,创建脚本如下: docker run -d -h service1 \ -v /Use ...
- Nginx设置Https反向代理,指向Docker Gitlab11.3.9 Https服务
目录 目录 1.GitLab11.3.9的安装 2.域名在阿里云托管,申请免费的1年证书 3.Gitlab 的 https 配置 4.Nginx 配置 https,反向代理指向 Gitlab 配置 目 ...
- nginx 为什么要反向代理 影藏后端 高效连接(给nginx,他自己返回) 端口冲突解决 多个服务
nginx 为什么要反向代理 影藏后端 高效连接(给nginx,他自己返回) 端口冲突解决 多个服务 单机使用反向代理可以根据不同url匹配到不同站点 rsync 的工作原理和应用实例 ...
- Dapr初体验之服务调用
初次理解服务调用 在微服务中,有一个难点就是:如果你想使用各个服务组件,你就得知道不同服务的地址和端口,也就是服务发现. 在传统应用我们是怎么做的?就是在web项目里配置上api地址,如下: 在一个w ...
- ngnix 反向代理
1 课程目标 掌握nginx+tomcat反向代理的使用方法. 掌握nginx作为负载均衡器的使用方法. 掌握nginx实现web缓存方法. 2 nginx介绍 2.1 ...
随机推荐
- Mac mini M1使用简单体验(编程、游戏、深度学习)
好久不见了各位! 前一阵子忍不住剁手买了M1芯片的mac mini,为了弥补自己的内疚感就卖了自己的旧的mbp2017款.数据也完全迁移到了新机器上,之前的工作也就由mbp2017彻底换成mac mi ...
- ASP.NET Core获取请求完整的Url
在ASP.NET项目中获取请求完整的Url: 获取System.Web命名空间下的类名为HttpRequestBase的Url方法: /// <summary>在派生类中替代时,获取有关当 ...
- 使用hive增量更新
目录 1.增量更新 2.对第一种情况 2.1.准备工作 2.2.更新数据 3.对第二种情况 3.1.准备工作 3.2.方法1 3.3.方法2 参考文末文章,加上自己的理解. 1.增量更新 有一个 ba ...
- Python爬虫系统化学习(3)
一般来说当我们爬取网页的整个源代码后,是需要对网页进行解析的. 正常的解析方法有三种 ①:正则匹配解析 ②:BeatuifulSoup解析 ③:lxml解析 正则匹配解析: 在之前的学习中,我们学习过 ...
- Python处理不平衡数据
参考文献 所谓的不平衡数据集指的是数据集各个类别的样本量极不均衡.以二分类问题为例,假设正类的样本数量远大于负类的样本数量,通常情况下通常情况下把多数类样本的比例接近100:1这种情况下的数据称为不平 ...
- Docker搭建Hadoop环境
文章目录 Docker搭建Hadoop环境 Docker的安装与使用 拉取镜像 克隆配置脚本 创建网桥 执行脚本 Docker命令补充 更换镜像源 安装vim 启动Hadoop 测试Word Coun ...
- JUC-ThreadLocalRandom
目录 Radndom类的局限性 ThreadLocalRandom 这个类是在JDK7中新增的随机数生成器,它弥补了Random类在多线程下的缺陷. Radndom类的局限性 在JDK7之前包括现在j ...
- 翻译:《实用的Python编程》03_02_More_functions
目录 | 上一节 (3.1 脚本) | 下一节 (3.3 错误检查) 3.2 深入函数 尽管函数在早先时候介绍了,但有关函数在更深层次上是如何工作的细节却很少提供.本节旨在填补这些空白,并讨论函数调用 ...
- go mod包管理 加代理下载
原始go.mod文件 module xxx go 1.14 报错 i/o timeout go mod init workorder go mod init: go.mod already exist ...
- 中小企业上云首选,华为云全新云服务器S6性能评测分析
转: 中小企业上云首选,华为云全新云服务器S6性能评测分析 [小宅按]今天,华为云全新弹性云服务器ECS通用计算型云服务器S6(以下简称为"华为云S6云服务器")正式发布,至顶网云 ...