使用 .NET Core、Emitter 和 JavaScript 进行实时 Twitter 流可视化
使用 Emitter 发布/订阅实时可视化推文流。使用 Docker 在 Linux 上部署 .NET Core。
引言
本文介绍了一个使用 C#/.NET Core 发布者应用程序捕获 Twitter 流、处理并将其通过 emitter 消息代理(也在 GitHub 上)实时重新发布文本和头像的 Twitter 示例流的可视化。该代理允许将流广播到用 JavaScript 编写的订阅客户端。
[查看实时演示]
背景
该应用程序的架构非常简单,但功能强大。我们有一个发布者应用程序,它从 Twitter API 消耗推文并将其发布到 Emitter Broker。该代理负责消息的多播和广播,用于将处理后的推文从发布者传输到 HTML5 消费者。
推文发布者(C#/.NET Core)
- 建立与 Twitter 流 API 和 Emitter Broker 的连接。
- 每次收到新推文时,都会处理该推文并将其发布到 `tweet-stream` 通道。
Javascript 客户端
- 订阅 `tweet-stream` 通道。
- 每次通过 `tweet-stream` 通道收到推文时,都会对其进行处理并绑定到视图。
推文发布者 - C#/.NET Core 应用程序
以下是我为该应用程序编写的大部分代码,该应用程序消耗 Twitter 流、对其进行处理并重新发布到 Emitter。
- 首先,它使用了非常出色且兼容 .NET Core 的 Twitter API:https://github.com/linvi/tweetinvi 来连接流和一个 `TweetReceived` 事件,该事件会在每次收到来自 Twitter 的消息时触发。
- 它建立与 Emitter 的连接并执行 Twitter 身份验证。如果您想自己尝试,请确保获取进行应用身份验证所需的 4 个安全密钥,这些密钥可以在此处找到:https://apps.twitter.com。
- 我们使用速率限制器,以便以稳定且视觉上令人愉悦的速率将推文显示给用户。
- 对于收到的每条推文,如果它是转推,我们就会跳过,然后简单地将 `Text` 和 `ProfileImageUrl400x400` 以 JSON 格式重新发布到 Emitter 的 `tweet-stream` 通道。
public class Program
{
public static void Main(string[] args)
{
// Connect to emitter
var emitter = Connection.Establish();
// Set up your credentials (https://apps.twitter.com)
Auth.SetUserCredentials(
Environment.GetEnvironmentVariable("CONSUMER_KEY"),
Environment.GetEnvironmentVariable("CONSUMER_SECRET"),
Environment.GetEnvironmentVariable("ACCESS_TOKEN"),
Environment.GetEnvironmentVariable("ACCESS_TOKEN_SECRET")
);
// Setup a rate limiter, only re-publish one tweet per 350 milliseconds
var limiter = new Throttle(1, TimeSpan.FromMilliseconds(350));
// Using the sample stream
var stream = Stream.CreateSampleStream();
stream.AddTweetLanguageFilter(LanguageFilter.English);
stream.FilterLevel = Tweetinvi.Streaming.Parameters.StreamFilterLevel.Low;
stream.TweetReceived += (sender, t) =>
{
// Skip retweets
if (t.Tweet.IsRetweet)
return;
// Limiter allows us to have a steady, visually pleasing rate of tweets
var ct = new CancellationToken();
limiter.Enqueue(() =>
{
// Publish the tweet to the broker
emitter.Publish(
"IsQ7z18uGEFpjOJpt4K6ij49klT3PGzu",
"tweet-stream",
JsonConvert.SerializeObject(new
{
avatar = t.Tweet.CreatedBy.ProfileImageUrl400x400,
text = t.Tweet.Text
}));
}, ct);
};
// Start
stream.StartStream();
}
}
推文发布者 - 使用 Docker 部署
我们将使用 Docker 来部署我们的小型 .NET Core 发布者。Docker 容器将一小段软件封装在一个完整的文件系统中,该文件系统包含运行所需的一切:代码、运行时、系统工具、系统库——任何可以在服务器上安装的东西。这保证了软件始终在相同的环境中运行,无论其部署环境如何。
开始最简单的方法之一是使用 Dockerfile 以及 Docker Hub Build Server,它将构建一个可以在目标机器上部署的镜像。Docker Hub 允许我们自动构建一个 Docker 镜像(在此处可以将其视为虚拟机镜像),然后我们可以部署它。可以触发该镜像在每次提交到 git 存储库时自动重新构建。
如下所示,我们的 Docker 文件做了几件事情,本质上是一个用于 **创建 Docker 镜像** 的脚本。
- 它从 Microsoft 提供的 .NET Core Docker 镜像开始。
- 更新 apt-get 源并克隆 Git 存储库。
- 执行 `dotnet restore`,它实际上执行 `nuget restore` 并加载所有依赖项。
- 执行 `dotnet publish`,它为我们的镜像创建最终的二进制文件。
- 挂载一个 `deploy.sh` 脚本,该脚本将在每次镜像启动时执行。此脚本只是运行我们的应用程序。
FROM microsoft/dotnet:1.0.0-preview2-sdk MAINTAINER Roman Atachiants "roman@misakai.com" # Make sure we have S3 & additional libraries RUN apt-get update -qq \ && apt-get install -y git \ && mkdir /tmp/emitter \ && cd /tmp/emitter \ && git clone "https://github.com/kelindar/twitter-stream.git" "/tmp/emitter" \ && cd /tmp/emitter \ && dotnet restore -v Minimal \ && cd /tmp/emitter/src/Server \ && dotnet publish -c Release --output /app \ && rm -rf /tmp/emitter # Application will be in app folder WORKDIR /app ADD deploy.sh / CMD ["/bin/bash", "/deploy.sh"]
镜像构建完成后,我们可以通过键入 `docker run -it kelindar/twitter-stream` 来启动它,假设您已安装 docker。它将自动从 Docker Hub 下载镜像并为我们交互式运行它。
Javascript 客户端
与我们刚才编写的 C# 应用程序类似,该客户端也非常简单明了。实际上,所有 JavaScript(不包括依赖项)都显示在下方。客户端执行几项操作:
- 连接到 emitter 发布/订阅服务。
- 使用 VueJS 设置我们的 ViewModel。
- 一旦我们连接到 emitter,它就会订阅 `tweet-stream` 通道。
- 每次收到消息时,我们将其推送到 ViewModel 的 `data` 属性中,该属性已绑定到 HTML DOM。
// Connect to emitter broker
var emitter = emitter.connect({
secure: true
});
var key = 'jtdQO-hb5jfujowvIKvSF41NeQOE8IoF';
var vue = new Vue({
el: '#app',
data: {
messages: []
}
});
emitter.on('connect', function(){
// once we're connected, subscribe to the 'tweet-stream' channel
console.log('emitter: connected');
emitter.subscribe({
key: key,
channel: "tweet-stream"
});
})
// on every message, print it out
emitter.on('message', function(msg){
// If we have already few messages, remove the oldest one (first)
if (vue.$data.messages.length >= 8){
vue.$data.messages.shift();
}
// Push the message we've received
vue.$data.messages.push(msg.asObject());
});
这里的 UI 大部分来自我之前的一篇文章,其中 emitter 用于创建一个简单的群聊。如果您有兴趣,欢迎查看 实时演示和相应的 CodeProject 文章。
历史
- 2016 年 4 月 12 日 - 文章的初始版本