从零开始使用Dapr简化微服务的示例
作者:福禄网络研发团队 发布时间:2021-01-26 09:39:30
序言
现有的微服务模式需要再业务代码中集成大量基础设施模块,比如注册中心,服务发现,服务调用链路追踪,请求熔断,重试限流等等,使得系统过于臃肿重量级。
Dapr作为新一代微服务模式,使用sidecar模式,简化了现有微服务系统代码,将基础设施层以sidecar模式分离,使得开发人员更集中于业务逻辑编写。
本文以net6和dapr1.5为基础,搭建一个dapr的简单使用示例。
1、安装Docker
Dapr的运行依赖于Docker环境。
作为学习环境,使用Centos 7系统安装Docker。
安装Docker推荐使用daocloud一键安装命令:
curl -sSL https://get.daocloud.io/docker | sh
安装完成后运行命令:
[root@localhost ~]# docker -v
Docker version 20.10.11, build dea9396
显示对应的Docker版本即安装成功。
2、安装Dapr CLI
官方解释:Dapr CLI 是您用于各种 Dapr 相关任务的主要工具。 您可以使用它来运行一个带有Dapr sidecar的应用程序, 以及查看sidecar日志、列出运行中的服务、运行 Dapr 仪表板。
下载Dapr CLI
wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash
验证安装情况
dapr -v
输出以下内容即安装成功。
CLI version: 1.5.0
Runtime version: 1.5.0
由于国内网络问题,使用官方的Dapr安装方法一般会遇到各种问题,因此把dapr下载下来,通过脚本进行安装。
修改hosts文件
vi /etc/hosts
140.82.114.4 github.com
199.232.69.194 github.global.ssl.fastly.net
140.82.114.9 codeload.github.com
刷新缓存
yum install -y nscd
service nscd restart
首先需要安装Git,然后执行以下命令:
git clone -v https://gitee.com/Two-Twoone/dapr-installer.git
cd dapr-installer/
./install.sh
虽然还是很慢,但是总比下不了好多了。
上面命令启动了几个容器,运行下列操作来验证:
[root@localhost dapr-installer]# docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}"
CONTAINER ID NAMES PORTS
a0565f609846 dapr_placement 0.0.0.0:50005->50005/tcp, :::50005->50005/tcp
c392f5cf7a18 dapr_redis 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp
2ee68c450b29 dapr_zipkin 9410/tcp, 0.0.0.0:9411->9411/tcp, :::9411->9411/tcp
3、安装Net6 SDK
rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
yum update
yum install dotnet-sdk-6.0
4、创建应用程序
创建2个项目分别为 product,cart 引用Dapr
dotnet add package Dapr.AspNetCore
Program.cs中对 的 AddDapr
调用将 DaprClient
类注册到 ASP.NET Core注入系统。 注册客户端后,现在可以将 的实例注入服务代码, DaprClient
以与 Dapr sidecar、构建基块和组件进行通信。
builder.Services.AddControllers().AddDapr();
4.1、服务调用
在微服务系统中,服务与服务间的调用必不可少,难点主要集中在服务所在位置,发生错误时如何重试,负载均衡等问题。
Dapr中使用sidecar 作为服务的反向代理模块来解决这些问题。
prodcut项目增加下列代码
[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
private ILogger<ProductController> _logger;
public ProductController(ILogger<ProductController> logger)
{
_logger = logger;
}
private static readonly List<string> products = new List<string> { "aa", "bb", "cc", "dd", "ee", "ff", "gg", "hh", "ii", "jj", "kk", "ll", "mm", "nn" };
[HttpGet]
public ActionResult Get()
{
_logger.LogInformation($"调用了获取商品方法");
string[] temps = new string[5];
for (int i = 0; i < 5; i++)
{
Random random = new Random(Guid.NewGuid().GetHashCode());
temps[i] = products[random.Next(0, products.Count - 1)];
}
return Ok( temps);
}
}
# 启动Product 项目
dapr run --app-id ProductDemo --app-port 5010 --dapr-http-port 7015 -- dotnet /root/www/product/Dapr.Product.Sample.dll --urls http://*:5010
cart项目增加下列代码,dapr支持http,grpc调用方式,这里以常用的webapi为例,使用http方式调用。
InvokeMethodAsync方法中appid对应的就是dapr run 中的appid,无需关系调用地址。
[Route("api/[controller]")]
[ApiController]
public class CartController : ControllerBase
{
private readonly DaprClient _daprClient;
private readonly ILogger<CartController> _logger;
public CartController(DaprClient daprClient, ILogger<CartController> logger)
{
_daprClient = daprClient;
_logger = logger;
}
[HttpGet]
[Route("GetProducts")]
public async Task<IActionResult> GetProducts()
{
_logger.LogInformation($" Cart 获取商品");
var products = await _daprClient.InvokeMethodAsync<List<string>>(HttpMethod.Get, "ProductDemo", "/api/Product/GetAll");
return Ok(products);
}
}
将程序上传到linux服务器,运行程序
# 启动 Cart 项目
dapr run --app-id CartDemo --app-port 5020 --dapr-http-port 7025 -- dotnet /root/www/cart/Dapr.Cart.Sample.dll --urls http://*:5020
调用接口,可以看到Cart项目几乎没有代码入侵就实现了接口调用。
[root@localhost ~]# curl -X 'GET' 'http://192.168.2.110:5020/api/Cart/GetProducts'
["aa","bb","cc","dd","ee","ff","gg","hh","ii","jj","kk","ll","mm","nn"]
Dapr内部使用了mDns进行了服务注册发现和负载均衡,部署多个product后调用,可以看到轮询调用效果。
在自承载模式下,Dapr 使用 mDNS 查找它。在 Kubernetes 模式下运行时,Kubernetes DNS 服务确定地址。
在调用失败和瞬态错误的情况下,服务调用会执行自动重试,Dapr 默认是开启了重试,所以接口不支持幂等是十分危险的行为。
4.2、发布订阅
? 发布订阅模式,主要是用于微服务间基于消息进行相互通信。你可能也会说,这也要拿出来说,我搞个RabbitMQ/Kafka就是了,
原来我们都会根据使用的组件引入不同的sdk,不同的消息队列监听、消费模式还不一样。
? Dapr 提供了一个构建基块,可显著简化实现发布/订阅功能,从而和底层基础设施解耦,编写业务逻辑时不需要关心是什么消息队列。
再Program中添加发布订阅支持
app.UseCloudEvents();
app.UseEndpoints(endpoints =>
{
endpoints.MapSubscribeHandler();
});
订阅消息,使用Topic特性,传递pubsub和主题名称
[Topic("pubsub", "newUser")]
public ActionResult subUserInfo(UserInfo us)
{
_logger.LogInformation($"接收到订阅消息 id:{us.id} name:{us.name},age:{us.age},sex:{us.sex}");
return Ok("处理完毕");
}
发布消息,使用dapr公开方法PublishEventAsync,传递pubsub和主题名称,以及消息体
[HttpPost]
public async Task<IActionResult> PubUserInfo(UserInfo us)
{
await _daprClient.PublishEventAsync("pubsub", "newUser", us);
return Ok();
}
消息发布订阅组件支持RabbitMQ,Redis,Kafka等。
4.3、状态管理
?Dapr 默认使用 Redis 作为状态存储。它也支持MongoDB,PostgreSQL,SQL Server等。
它不会对上层暴露底层用的那个中间件,也就是说在不同环境下可以使用同一套代码来使用不同的中间件。
[HttpPost]
[Route("SaveUserList")]
public async Task<IActionResult> SaveUserList()
{
var temps = new List<UserInfo>
{
new UserInfo("小红",1,true,Guid.NewGuid().ToString()),
new UserInfo("小黄",1,true,Guid.NewGuid().ToString()),
new UserInfo("小蓝",1,true,Guid.NewGuid().ToString())
};
await _daprClient.SaveStateAsync("statestore", "UserList", temps);
return Ok(1);
}
[HttpGet]
[Route("GetUserList")]
public async Task<IActionResult> GetUserList()
{
var list = await _daprClient.GetStateAsync<List<UserInfo>>("statestore", "UserList");
return Ok(list);
}
[HttpGet]
[Route("DeleteUserList")]
public async Task<IActionResult> DeleteUserList()
{
await _daprClient.DeleteStateAsync("statestore", "UserList");
return Ok(1);
}
public record UserInfo(string name, int age, bool sex, string id);
4.4、链路追踪
传统微服务中,要实现链路追踪,对代码的侵入强。
Dapr 在 Sidecar 中添加了一个 http/grpc中间件。拦截所有应用程序流量,并自动注入关联 ID 以跟踪分布式事务。
使用 Zipkin 协议进行分布式跟踪,无需代码检测,使用可配置的跟踪级别自动跟踪所有流量。
?5、总结
?本文只是对Dapr做了一个简单示例,对各个组件具体的实现原理没有做过多深入讲解。
?Dapr区别于传统微服务框架最大的优点就是Sidecar 。以前的微服务框架都需要代码项目引用微服务相关的一些类库,无论是服务注册发现、熔断、配置等都是要调用对应类库实现,这些类库是运行在微服务的进程中的,因此这些类库都需要使用和业务代码一样(或者兼容)的语言来开发,因此是比较重的。
?而Sidecar 这种模式,把“注册发现、熔断、配置”等这些微服务的功能都剥离到一个和业务代码的进程相伴而行的独立进程中,业务代码通过http或者grpc等方式和这个Sidecar 进程通讯来完成微服务的相关服务的调用。
?显而易见,在Sidecar 这种模式中,业务代码中只有极少数和Sidecar 进程通讯的代码,因此非常轻量级。这样Sidecar 进程中的服务可以独立升级,模块可以自由组合,不会干扰业务代码。同时由于Sidecar 的进程是独立的进程,业务代码和Sidecar 进程通讯是采用http、grpc这样语言无关的协议,因此业务代码可以采用任何语言来进行开发。
来源:https://www.cnblogs.com/fulu/p/15607750.html


猜你喜欢
- 一. 环境变量$PATH:Linux是一个多用户操作系统,每个用户都有自己专有的运行环境。用户所使用的环境由一系列变量所定义,这些变量被称为
- 我是一个农村的90后站长,搞网站4年了,对于网站宣传有一些研究。网站做好了肯定是想让更多的人看到,毕竟是咱的心血,没有人看怎么行。那么我们就
- 23. 服务名称: helpsvc显示名称: Help and Support服务描述: 启用在此计算机上运行帮助和支持中心。如果停止服务,
- 从事搜索引擎优化的人员都非常清楚,原创性内容对于搜索引擎优化的意义,特别是在08年下半年开始,百度对于网页重复内容的过滤更加严格了,搜索引擎
- ansibleansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、f
- 我现在做的站已经成了我们本地最大的一个地方站,内容涉及很多方面,当初最站的时候,并没有想到要做一个大而全的地方门户网站,只是想做一个摄影交流
- 因为需要更改电子邮件,你也许想加强多个电子邮件帐户或者把不同的地址组织到不同的帐户里。要这样做,你不需要取消或者重新创建你的电子邮件帐户或者
- 为了更好的实现对社区热点信息的聚焦,Discuz! 7.1新增了“热点话题”功能,成为强化社区信息聚焦重要应用手段。重视细节改进是产品发展的
- 开启视频功能今天,笔者详细给大家介绍一下,如何使用Discuz!6.0论坛中的视频上传和在线录制功能。站长如何开启视频功能:使用Discuz
- 网络营销已经成为旅游行业一种至关重要的推广模式,几乎所有的旅行社都拥有自己的网站,综合类的旅游网站也让人目不暇接,竞争之激烈可谓战火纷飞。但
- 随着时代的不断发展和推进,我们看到了今天的互联网也在逐渐的完善和成熟,回眸一下05年前的站长圈子,那个时候大家都很单纯的在讨论网络技术,没有
- 很久没更新了,今天(12月11日)新增三个网摘代码,分别是飞豆、抓虾、鲜果,这些都是著名的网摘网站。你可以在此篇文章最后看到新增的网摘代码。
- CentOS下RabbitMq高可用集群环境搭建教程分享给大家。准备工作1、准备两台或多台安装有rabbitmq-server服务的服务器我
- URL优化的重点就是把内容放在权重高的页面上,以下是各级目录的权重比较。1)目录的权重虽然搜索蜘蛛会捉取3级目录及以上的页面,但是一级目录的
- Linux下安装zip解压功能Linux服务器上一般默认没是没有有安装zip命令安装zip指令apt-get install zip 或 y
- 随着docker使用的镜像越来越多,就需要有一个保存镜像的地方,这就是仓库。目前常用的两种仓库:公共仓库和私有仓库。最方便的就是使用公共仓库
- 根据不同的划分标准,网站可分成好几种类型,如将网站按照主体性质不同可分为政府网站、企业网站、商业网站、教育科研机构网站、个人网站、其它非盈利
- Ubuntu下安装并配置VS Code编译C++安装VS Codesudo add-apt-repository ppa:ubuntu-de
- 部署禁止中文浏览器访问网站 在网站的根目录中的 htaccess 文件中,增加如下语句 #####################
- 近年来,SEO和SEM在网络营销领域中显得越来越重要了。由于名字相近,人们经常同时讲到它们。不少人经常将二者混淆,因此思亿欧再来具体说明一下