Yarp 让系统内调度更灵活
简介
Yarp 是微软团队开发的一个反向代理组件, 除了常规的 http 和 https 转换通讯,它最大的特点是可定制化,很容易根据特定场景开发出需要的定制代理通道。
详细介绍:https://devblogs.microsoft.com/dotnet/announcing-yarp-1-0-release
源码仓库:https://github.com/microsoft/reverse-proxy
文档地址 :https://microsoft.github.io/reverse-proxy/
基础使用
1、创建 ASP.NET Core 空项目
使用 Visual Studio :
dotnet new web -o MyProxy
2、 修改代码 Program.cs 文件
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();
app.MapGet("/Ping", () => "Hello World!");
app.MapReverseProxy();
app.Run();
3、修改配置文件 appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ReverseProxy": {
"Routes": {
"routeAll": {
"ClusterId": "clusterBaidu",
"Match": {
"Path": "{**catch-all}"
}
}
},
"Clusters": {
"clusterBaidu": {
"Destinations": {
"baidu": {
"Address": "https://www.baidu.com/"
}
}
}
}
}
}
这里的配置是将所有的请求都转发到百度。
在 Program.cs 里,还注册了一个 Get 路由 Ping 。
4、启动项目
能够看到在浏览器访问程序监听的端口号后,显示的是百度的页面。打开 F12 ,看到请求头也是本地的,并不是百度的域名。
测试手动注册的路由 Ping :
能够显示正常。
5、问题整理
(1) Yarp 是不是只能做这种简单的转发?
不是,往下有配置文件说明。
(2) JSON 配置文件里有什么要注意的地方吗?
有。在这个演示的配置文件中 ReverseProxy:Clusters:cluster1:Destinations:destination1:Address 对应的值是:https://www.baidu.com/ ,如果去掉 www ,在项目启动后会跳转到百度首页,不是代理转发。去掉末尾的 / 符合没有任何影响。
(3) Yarp 会影响到程序中注册的路由吗?
不会影响到程序内部注册的路由。在 Program.cs 中无论 app.MapReverseProxy(); 在上还是在下,在访问 Ping 的时候,都是返回 Hello World!
var app = builder.Build();
app.MapReverseProxy();
app.MapGet("/Ping", () => "Hello World!");
app.Run();
进阶探索
1、多地址代理
修改配置文件 appsettings.json ,实现默认路由跳转百度,当访问 /movie 是访问 b站。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ReverseProxy": {
"Routes": {
"routeBaidu": {
"ClusterId": "clusterBaidu",
"Match": {
"Path": "{**catch-all}"
}
},
"routeBiliBili": {
"ClusterId": "clusterBiliBili",
"Match": {
"Path": "/movie/{**catch-all}"
}
}
},
"Clusters": {
"clusterBaidu": {
"Destinations": {
"baidu": {
"Address": "https://www.baidu.com/"
}
}
},
"clusterBiliBili": {
"Destinations": {
"bilibili": {
"Address": "https://www.bilibili.com/"
}
}
}
}
}
}
测试结果:
在后面输入路由 /movie 后能够跳转到b站。但是b站网页没有完整显示,图片都没有,这是网站上的策略问题,对于数据接口没有这些问题。
详细的配置文件说明,可以查看 https://microsoft.github.io/reverse-proxy/articles/config-files.html
2、规则匹配
网页上太多资源,为了方便测试,启用两个 api 接口。地址分别是:http://localhost:5241/ 和 https://localhost:7184/
两个 api 接口中分别注册 /test 路由。
// http://localhost:5241/
app.MapGet("/test", () => "Welcome to Api111!");
// https://localhost:7184/
app.MapGet("/test", () => "Welcome to Api222!");
启动两个 api 程序。
C:\Users\Test>curl http://localhost:5241/test
Welcome to Api111!
C:\Users\Test>curl https://localhost:7184/test
Welcome to Api222!
修改 MyProxy 项目的配置文件 appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ReverseProxy": {
"Routes": {
"routeOne": {
"ClusterId": "clusterOne",
"Match": {
"Path": "/test/{**catch-all}",
"QueryParameters": [
{
"Name": "number",
"Values": [ "1" ]
}
]
}
},
"routeTwo": {
"ClusterId": "clusterTwo",
"Match": {
"Path": "/test/{**catch-all}",
"QueryParameters": [
{
"Name": "number",
"Values": [ "2" ]
}
]
}
},
"routeBaidu": {
"ClusterId": "clusterBaidu",
"Match": {
"Path": "{**catch-all}"
}
}
},
"Clusters": {
"clusterOne": {
"Destinations": {
"apiOne": {
"Address": "http://localhost:5241/"
}
}
},
"clusterTwo": {
"Destinations": {
"apiTwo": {
"Address": "https://localhost:7184/"
}
}
},
"clusterBaidu": {
"Destinations": {
"baidu": {
"Address": "https://www.baidu.com/"
}
}
}
}
}
}
Path :监听路由地址。
QueryParameters:匹配参数。
QueryParameters:Name:参数名。
QueryParameters:Values:参数值。
MyProxy 的监听端口是 http://localhost:5024/ 访问结果如下:
C:\Users\Test>curl http://localhost:5024/ping
Hello World!
C:\Users\Test>curl http://localhost:5024/test
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /test was not found on this server.</p>
</body></html>
C:\Users\Test>curl http://localhost:5024/test?number=1
Welcome to Api111!
C:\Users\Test>curl http://localhost:5024/test?number=2
Welcome to Api222!
能够根据参数以及参数值导向对应的地址。
3、问题整理
(1)为什么访问 /movie 不能正常显示网页。
因为 b站某些接口开启了防盗链,还有跨域检测。
(2)在根据参数匹配中,如果匹配的路由一样,监听的参数一样,参数值也一样会怎么样?
访问该路由地址会报错。
(3)路由匹配的优先级?
程序内注册的路由优先级最高,其次才是 Yarp 在配置文件里加载的。
小试牛刀
加班写业务中,待完成。
踩坑集锦
1、non-ASCII
项目要代理某网页,在使用下载功能的时候,接口返回 502 。
info: Yarp.ReverseProxy.Forwarder.HttpForwarder[48]
ResponseHeaders: The destination returned a response that cannot be proxied back to the client.
System.InvalidOperationException: Invalid non-ASCII or control character in header: 0x00E4
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowInvalidHeaderCharacter(Char ch)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ValidateHeaderValueCharacters(StringValues headerValues)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseHeaders.SetValueFast(String key, StringValues value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.Microsoft.AspNetCore.Http.IHeaderDictionary.set_Item(String key, StringValues value)
at Yarp.ReverseProxy.Forwarder.HttpTransformer.CopyResponseHeaders(HttpHeaders source, IHeaderDictionary destination)
at Yarp.ReverseProxy.Forwarder.HttpTransformer.TransformResponseAsync(HttpContext httpContext, HttpResponseMessage proxyResponse)
at Yarp.ReverseProxy.Transforms.Builder.StructuredTransformer.TransformResponseAsync(HttpContext httpContext, HttpResponseMessage proxyResponse)
at Yarp.ReverseProxy.Forwarder.HttpForwarder.SendAsync(HttpContext context, String destinationPrefix, HttpMessageInvoker httpClient, ForwarderRequestConfig requestConfig, HttpTransformer transformer)
去 GitHub 翻 Issues
下载接口能正常访问,文件流也能完整地拿到。重写了所有的响应头没有用。这种不开源的商业站点,也猜不到字符编码。
最后妥协了,用了一个 .NET 服务在服务器上下载后再转发。
代理非常规服务接口时,一定要多测试。
Yarp 让系统内调度更灵活的更多相关文章
- 编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程
建议56:使用继承ISerializable接口更灵活地控制序列化过程 接口ISerializable的意义在于,如果特性Serializable,以及与其像配套的OnDeserializedAttr ...
- bootstrap3-dialog:更强大、更灵活的模态框(封装好的模态框)
用过bootstrap框架的同学们都知道,bootstrap自带的模态框用起来很不灵活,可谓鸡肋的很.但nakupanda开源作者封装了一个更强大.更灵活的模态框——bootstrap3-dialog ...
- bootstrap3-dialog:更强大、更灵活的模态框
用过bootstrap框架的同学们都知道,bootstrap自带的模态框用起来很不灵活,可谓鸡肋的很.但nakupanda开源作者封装了一个更强大.更灵活的模态框——bootstrap3-dialog ...
- graphicview和widgets没本质区别。它只是更轻量级,更灵活,性能更高的widgets
graphicview和widgets没本质区别.它只是更轻量级,更灵活,性能更高的widgets.核心就是把widgets变成了更轻量级的graphicitem,把QWidget的各种事件转换成了g ...
- 【转】编写高质量代码改善C#程序的157个建议——建议56:使用继承ISerializable接口更灵活地控制序列化过程
建议56:使用继承ISerializable接口更灵活地控制序列化过程 接口ISerializable的意义在于,如果特性Serializable,以及与其像配套的OnDeserializedAttr ...
- xmake从入门到精通12:通过自定义脚本实现更灵活地配置
xmake是一个基于Lua的轻量级现代化c/c++的项目构建工具,主要特点是:语法简单易上手,提供更加可读的项目维护,实现跨平台行为一致的构建体验. 本文主要详细讲解下,如何通过添加自定义的脚本,在脚 ...
- 源码分析:Phaser 之更灵活的同步屏障
简介 Phaser 是 JDK 1.7 开始提供的一个可重复使用的同步屏障,功能类似于CyclicBarrier和CountDownLatch,但使用更灵活,支持对任务的动态调整,并支持分层结构来达到 ...
- 如何用Serverless让SaaS获得更灵活的租户隔离和更优的资源开销
关于SaaS和Serverless,相信关注我的很多读者都已经不陌生,所以这篇不会聊它们的技术细节,而将重点放在SaaS软件架构中引入Serverless之后,能给我们的SaaS软件带来多大的收益. ...
- Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制
新的锁定类提高了同步性 —— 但还不能现在就抛弃 synchronized JDK 5.0为开发人员开发高性能的并发应用程序提供了一些很有效的新选择.例如,java.util.concurrent.l ...
随机推荐
- Upload-labs通关指南(上) 1-10
Upload-labs 所有文章和随笔(随笔将不于csdn更新)将于我的个人博客(移动端暂未适配)第一时间更新. 一些网站存在文件上传接口,一旦存在这个接口就有可能存在漏洞. 文件上传漏洞的逻辑是将一 ...
- javascript-jquery介绍
jquery优势 1.轻量级 2.强大的选择器 3.出色的DOM封装 4.可靠的事件处理机制 5.完善的Ajax 6.不污染顶级变量 7.出色的浏览器兼容 8.链式操作方式 9.隐式迭代 10.行为层 ...
- [no_code][Beta]事后分析
设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的目前的手写表单的电子化问题,办公电子化问题的一个key问题.定义十分清楚: 输入: 手写表单 ...
- 【二食堂】Alpha - Scrum Meeting 3
Scrum Meeting 3 例会时间:4.13 12:00 - 12:30 进度情况 组员 昨日进度 今日任务 李健 1. 继续学习前端知识,寻找一些可用的框架.issue 1. 搭建主页html ...
- Manjaro / ArchLinux 安装网易云音乐解决搜索不能输入中文方法
0. 安装网易云音乐 yay -S netease-cloud-music 1.先安装qcef这个软件包. sudo yay -S qcef 2.编辑/opt/netease/netease-clou ...
- RocketMQ源码详解 | Producer篇 · 其一:Start,然后 Send 一条消息
概述 DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); ...
- 2021.8.14考试总结[NOIP模拟39]
T1 打地鼠 全场就俩人没切,还有一个是忘关$freopen$了. $code:$ 1 #include<bits/stdc++.h> 2 #define rin register sig ...
- Python课程笔记(九)
本次课程主要学习了Excel和JSON格式的一些读写操作.课程代码 一.Excel数据读写操作 1.安装模块 pip install xlrd pip install xlwt 网不好可以采用三方库: ...
- NOIP 模拟 八十五
T1 冲刺NOIP2021模拟18 莓良心 容易发现答案和每一个 \(w_i\) 无关,我们只需要求出总和然后计算方案数. 对于每一个数贡献的方案数是相同的,首先是自己的部分就是\(\begin{Bm ...
- vue混入mixin的使用,保证你看的明明白白!
场景描述 有些时候,我们发现有些组件部分功能代码是几乎是一样的. 这个时候,我们就可以将相同的逻辑代码抽离出来 此时我们的主角混入mixin就登场了 下面我们有a-test和b-test两个组件,点击 ...