vuejs和nodejs
In this article I cover a number of different concepts and technologies; Web Sockets, Python, Node, Vue JS, Docker, and bring them all together in a microservice architecture.
在本文中,我介绍了许多不同的概念和技术。 Web套接字,Python,Node,Vue JS,Docker,并将它们整合到微服务架构中。
Each component in this stack will be a microservice. I will take you through building each one, including running them in separate Docker containers.
此堆栈中的每个组件都是微服务。 我将指导您构建每个组件,包括在单独的Docker容器中运行它们。
为什么选择微服务 (Why Microservices)
Microservices bring with them immense flexibility, scalability, and fault tolerance. Today we will only cover the flexibility. Scalability and Fault tolerance require other technologies such as Kubernetes which are outside the scope of this article.
微服务带来了巨大的灵活性,可扩展性和容错能力。 今天,我们只讨论灵活性。 可伸缩性和容错能力需要其他技术,例如Kubernetes,这不在本文的讨论范围之内。
The flexibility of Microservices is created by each service being independent of the others and importantly only doing one job.
微服务的灵活性是由每项服务彼此独立并且重要的是仅完成一项工作而创建的。
Taking the example we are looking at in this article, we could easily swap out the VueJS front end and replace it with react.
以我们在本文中看到的示例为例,我们可以轻松地换出VueJS前端并将其替换为react。
Or we could add a Mongo DB Microservice and store all tweets for analysis at a later date.
或者,我们可以添加Mongo DB Microservice并存储所有推文以供日后分析。
示范现场 (Demo site)
I have setup a demo site of what I am going to develop in this article. You can view it here http://medium-microservices.simoncarr.co.uk/
我已经设置了一个本文将要开发的演示站点。 您可以在这里查看它http://medium-microservices.simoncarr.co.uk/
Of course this is just the VueJS front end, but underneath all the goodness of Python, Node, WebSockets and Docker are at work.
当然,这只是VueJS的前端,但是在Python的所有优点的背后,Node,WebSocket和Docker都在起作用。
我对这个项目的态度 (My approach to this project)
Here is how I am going to approach this project
这就是我要如何处理这个项目的方法
- Develop the Python app and confirm we are receiving tweets 开发Python应用并确认我们收到了推文
- Develop the Web Socket service 开发Web Socket服务
- Connect the Python App to the Web Socket service 将Python App连接到Web Socket服务
- Develop the Vue JS front end and connect it to the WebSocket Service 开发Vue JS前端并将其连接到WebSocket服务
- Create docker images for each of the 3 Micro Services 为3个微服务中的每一个创建docker映像
- Create a Docker stack using docker-compose 使用docker-compose创建Docker堆栈
- Deploy the stack 部署堆栈
GitHub上的代码 (Code on GitHub)
All of the code for this project is available on GitHub
该项目的所有代码都可以在GitHub上找到
Twitter Client (Python)https://github.com/simonjcarr/medium_microservices_twitter_client
Twitter客户端(Python) https://github.com/simonjcarr/medium_microservices_twitter_client
Websocket server (NodeJS)https://github.com/simonjcarr/medium_microservices_websocket_server
Websocket服务器(NodeJS) https://github.com/simonjcarr/medium_microservices_websocket_server
Twitter stream UI (VueJS)https://github.com/simonjcarr/medium_microservices_twitter_ui
Twitter流UI(VueJS) https://github.com/simonjcarr/medium_microservices_twitter_ui
docker-compose file https://github.com/simonjcarr/medium_microservices_docker_composeThe images used in the docker-compose file need to be built first. You can use the Dockerfile’s in the above repos or follow the rest of this article to learn how to do it.
docker-compose文件 https://github.com/simonjcarr/medium_microservices_docker_compose 首先需要构建docker-compose文件中使用的映像。 您可以在上面的存储库中使用Dockerfile,或者按照本文的其余部分学习如何做。
创建一个推特应用 (Creating a twitter app)
Before we can receive tweets from Twitter, we will have to register an app at https://developer.twitter.com/
在我们可以从Twitter接收推文之前,我们必须在https://developer.twitter.com/上注册一个应用程序。
Once you have registered an App, a set of API keys will be generated that we can use to connect to the Twitter API.
一旦您注册了一个应用程序,就会生成一组API密钥,我们可以使用它们来连接到Twitter API。
In your browser navigate to https://developer.twitter.com/. If you don't already have one register an account.
在浏览器中,浏览至https://developer.twitter.com/ 。 如果您还没有人,请注册一个帐户。
After logging in, click on
Developer portal
登录后,单击
Developer portal
Hover your mouse over your username and from the dropdown menu, click
Apps
将鼠标悬停在用户名上方,然后从下拉菜单中单击
Apps
Click
Create App
and fill in the form you're presented with.点击
Create App
然后填写显示的表单。Once your app is created, you can retrieve your API credentials. There are two sets of credentials
Consumer API keys
andAccess token & Access token secret
. You will need both sets of keys shortly for use in the Python App.创建应用后,您可以检索API凭据。 有两组凭据(
Consumer API keys
和Access token & Access token secret
。 您很快将需要两组密钥才能在Python App中使用。
创建一个项目文件结构 (Create a project file structure)
Create a folder called microservices
创建一个名为microservices
的文件夹
We will create folders for each of our individual microservices as we go along. For now, we will just need another folder for the Python twitter client.
我们将继续为每个单独的微服务创建文件夹。 现在,我们只需要Python Twitter Twitter客户端的另一个文件夹即可。
In the microservices folder, create a subfolder called twitter_client
在微服务文件夹中,创建一个名为twitter_client
的子文件夹
创建Python Twitter客户端 (Creating the Python Twitter client)
Make sure you are using Python 3. As of writing this article, I am using Python 3.7.6
确保您使用的是Python3。撰写本文时,我正在使用Python 3.7.6
I would recommend that you use a virtual python environment. I’m going to use pipenv. If you don’t already have pipenv you can install it with
我建议您使用虚拟python环境。 我将使用pipenv。 如果您还没有pipenv,则可以使用
pip install --user pipenv
making sure you're in the twitter_client
folder and run
确保您位于twitter_client
文件夹中并运行
pipenv install tweepy python-dotenv
I’m going to be using Tweepy to connect to the twitter API. I am also installing python-dotenv
. This will allow me to put the Twitter API keys in a file called .dot
. This file will not be uploaded to git, so I know my Twitter API keys will remain secret.
我将使用Tweepy连接到twitter API。 我也在安装python-dotenv
。 这将允许我将Twitter API密钥放在名为.dot
的文件中。 该文件不会上传到git,所以我知道我的Twitter API密钥将保持秘密。
Create two new files
创建两个新文件
- twitter_client.py twitter_client.py
- .env .env
Open the .env
file in your code editor of choice and add the following lines. Replace the place holders <…> with the relevant keys from the app you registered in your twitter developer account.
在您选择的代码编辑器中打开.env
文件,并添加以下行。 用您在Twitter开发者帐户中注册的应用程序中的相关密钥替换占位符<…>。
API_KEY=""
API_SECRET_KEY=""
ACCESS_TOKEN=""
ACCESS_TOKEN_SECRET=""
Open twitter_client.py
and add the following code.
打开twitter_client.py
并添加以下代码。
import tweepy
from dotenv import load_dotenv
import os
load_dotenv()
auth = tweepy.OAuthHandler(os.getenv("API_KEY"), os.getenv("API_SECRET_KEY"))
auth.set_access_token(os.getenv("ACCESS_TOKEN"),
os.getenv("ACCESS_TOKEN_SECRET"))
api = tweepy.API(auth)
class TwitterListener(tweepy.StreamListener):
def on_status(self, status):
print(status.text)
twitterListener = TwitterListener()
myStream = tweepy.Stream(auth=api.auth, listener=twitterListener)
myStream.filter(track=['javascript', 'nodejs', 'python'])
In the code above, I create an auth object from tweepy
then I create a class TwitterListener
that extends tweepy.StreamListener
The on_status
method simply prints the text of each tweet that is received. To start receiving tweets, I instantiate TwitterListener, create a new stream, and then add a filter to only receive tweets that contain one or all of the following values javascript
, nodejs
, or python
在上面的代码中,创建从一个auth对象tweepy
然后我创建一个类TwitterListener
延伸tweepy.StreamListener
的on_status
方法简单地打印接收到的每个鸣叫的文本。 为了开始接收推文,我实例化了TwitterListener,创建了一个新的流,然后添加了一个过滤器以仅接收包含以下一个或所有以下值的推文: javascript
, nodejs
或python
If you run twitter_client.py
now you should see a stream of tweets scroll up the terminal. It will continue to display new tweets in real-time until you stop the script.
如果现在运行twitter_client.py
您应该会看到twitter_client.py
推文在终端上滚动。 它将继续实时显示新的推文,直到您停止脚本为止。
If like me, you are using pipenv, you can run the script like so
如果像我一样,您正在使用pipenv,则可以像这样运行脚本
pipenv run python twitter_client.py
创建Web套接字服务 (Creating the Web Socket service)
Now we know we can receive tweets, I am going to create the Web Socket service. I will use NodeJS to create this service.
现在我们知道可以接收到推文了,我将创建Web Socket服务。 我将使用NodeJS创建此服务。
If you don’t have NodeJS already installed you will need to visit the NodeJS Website https://nodejs.org/ and follow the instructions to download and install it.
如果尚未安装NodeJS,则需要访问NodeJS网站https://nodejs.org/,并按照说明进行下载和安装。
I am using NodeJS version 12.13.1
我正在使用12.13.1
版本
Create a new folder in the microservices
folder called websocket_server
在microservices
文件夹中创建一个名为websocket_server
的新文件夹
Make sure you're in the websocket_server
folder and enter the following command
确保您位于websocket_server
文件夹中,然后输入以下命令
npm init -y
This command will create a package.json
file that will hold the project dependencies.
此命令将创建一个package.json
文件,该文件将保存项目依赖项。
Enter the following command to install the ws
module
输入以下命令以安装ws
模块
npm i ws
Create a new file called app.js
and open it in your code editor and add the code below
创建一个名为app.js
的新文件,并在代码编辑器中将其打开,然后在下面添加代码
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 8088 })
wss.broadcast = function broadcast(data) {
wss.clients.forEach((client) => {
client.send(data)
})
}
wss.on('connection', (ws) => {
ws.on('message', (message) => {
try {
wss.broadcast(message)
}
catch (err) {
console.log(err)
}
})
The web socket server code is surprisingly simple. I am running the server on port 8088
(line 3)
Web套接字服务器代码非常简单。 我正在端口8088
(第3行)上运行服务器
Whenever the server receives a new message (line 13) it will resend the message to any clients that are connected by calling the broadcast function I have created. This simply loops through each connected client, sending the data to each (line 8)
每当服务器接收到新消息时(第13行),它将通过重新调用我创建的广播功能将消息重新发送给连接的所有客户端。 这简单地循环遍历每个连接的客户端,将数据发送到每个客户端(第8行)
Start the server by running the following command in the console in the websocket_server
folder.
通过在控制台的websocket_server
文件夹中运行以下命令来启动服务器。
node app.js
You won't see anything yet, as the server is not receiving any data. We are going to sort that out now by updating the Python Twitter client.
您尚未看到任何内容,因为服务器未接收到任何数据。 我们现在将通过更新Python Twitter客户端进行梳理。
将Twitter客户端连接到Web套接字服务器 (Connect the twitter client to the web socket server)
open a new terminal and navigate to the root of the twitter_client
folder that holds the python code.
打开一个新终端,然后导航到包含python代码的twitter_client
文件夹的根目录。
We need to install a python module that will create a WebSocket client and connect to the WebSocket server. Enter the following command
我们需要安装一个python模块,该模块将创建一个WebSocket客户端并连接到WebSocket服务器。 输入以下命令
pipenv install websocket-client
Using the client is even simpler than the WebSocket server and only requires 3 lines of code. Update twitter_client.py
so it contains the following code.
使用客户端甚至比WebSocket服务器更简单,只需要3行代码。 更新twitter_client.py
,使其包含以下代码。
import tweepy
from dotenv import load_dotenv
import os
from websocket import create_connection
import json
load_dotenv()
ws = create_connection("ws://localhost:8088")
auth = tweepy.OAuthHandler(os.getenv("API_KEY"), os.getenv("API_SECRET_KEY"))
auth.set_access_token(os.getenv("ACCESS_TOKEN"),
os.getenv("ACCESS_TOKEN_SECRET"))
api = tweepy.API(auth)
class TwitterListener(tweepy.StreamListener):
def on_status(self, status):
ws.send(json.dumps(status._json))
print(status._json)
twitterListener = TwitterListener()
myStream = tweepy.Stream(auth=api.auth, listener=twitterListener)
myStream.filter(track=['javascript', 'nodejs', 'python'])
The lines I have added are
我添加的行是
Line 4 import
create_connection
第4行导入
create_connection
Line 8 creates a new connection and assign to a variable
ws
第8行创建一个新的连接并分配给变量
ws
- Line 17 Each time a new tweet arrives, send the text of the tweet to the server 第17行:每当有一条新的tweet到达时,将该tweet的文本发送到服务器
I have also imported json
on line 5. The status object created by the tweepy module provides a number of items that represent each tweet. It also includes a _json
item that represents the original raw JSON received from Twitter. I’m using json.dumps()
to convert the JSON to a string that can be sent through the WebSocket connection.
我还进口json
上线5由tweepy模块创建的状态对象提供了许多表示每个鸣叫项目。 它还包含一个_json
项,代表从Twitter接收的原始原始JSON。 我正在使用json.dumps()
将JSON转换为可以通过WebSocket连接发送的字符串。
You can now restart the twitter_client.py
with the command
您现在可以使用以下命令重新启动twitter_client.py
pipenv run python twitter_client.py
If you open the terminal where the python twitter client
is running, you’ll see tweets scrolling up the screen.
如果打开运行python twitter client
的终端,则会在屏幕上看到推文滚动。
I’m going to leave the console debug messages in the code until the VueJS client is complete, so I know everything is running.
在VueJS客户端完成之前,我将在代码中保留控制台调试消息,因此我知道一切都在运行。
创建VueJS前端 (Creating the VueJS frontend)
This is where I start bringing it all together in a pretty front end, so tweets can be viewed in the web browser.
这是我在漂亮的前端将所有内容放在一起的地方,因此可以在Web浏览器中查看推文。
Open a new terminal window and navigate to the microservices
folder.
打开一个新的终端窗口,然后导航到microservices
文件夹。
If you don’t already have the VueJS CLI installed, enter the following command to install it.
如果尚未安装VueJS CLI,请输入以下命令进行安装。
npm i -g @vue/cli
You can find out more about VueJS at https://vuejs.org/
您可以在https://vuejs.org/上找到有关VueJS的更多信息。
Now create a new Vue app by entering the following command.
现在,通过输入以下命令来创建新的Vue应用。
vue create twitter_ui
You will first be prompted to pick a preset, use the up/down arrows on the keyboard to select Manually select features
and hit enter.
首先将提示您选择一个预设,使用键盘上的向上/向下箭头选择“ Manually select features
然后按Enter。
Now you're asked to select the features you want to install. You select/deselect features by using the up/down arrows and using the space bar to toggle a feature on or off.
现在,要求您选择要安装的功能。 您可以使用向上/向下箭头并使用空格键来选择/取消选择功能。
Here are the features you should choose for this project, make sure to select the same in your project. If any of these features are not available in your list of options, try running npm i -g @vue/cli
to make sure you have the latest version.
这是您应该为此项目选择的功能,请确保在项目中选择相同的功能。 如果您的选项列表中没有这些功能,请尝试运行npm i -g @vue/cli
以确保您具有最新版本。
Hit enter when you're finished. You will be asked to select the configuration for each of the features you selected. Here are the choices you should make
完成后,按Enter键。 系统将要求您为所选的每个功能选择配置。 这是您应该做出的选择
Choose a version of Vue.js:
2.x
选择一个Vue.js版本:
2.x
Pick a CSS pre-processor:
Sass/SCSS (with node-sass)
选择一个CSS预处理器:
Sass/SCSS (with node-sass)
Pick a linter:
ESLint + Prettier
选择一个
ESLint + Prettier
:ESLint + Prettier
Pick additional Lint features:
Lint on save
选择其他Lint功能:
Lint on save
Where to place config files:
In dedicated config files
放置配置文件的位置:
In dedicated config files
Save this as a preset:
No
将此保存为预设:
No
Once the installation has completed, cd into the folder twitter_ui
created by the Vue CLI.
安装完成后,将CD插入Vue CLI创建的文件夹twitter_ui
。
I am going to style this app using tailwind CSS
Installing and configuring tailwind in Vue is easy, simply enter the command below.
我将使用tailwind CSS
此应用程序的tailwind CSS
在Vue中安装和配置tailwind很容易,只需在下面输入命令即可。
vue add tailwind
When prompted, choose Minimal
. Job done!
出现提示时,选择Minimal
。 任务完成!
It’s helpful here to open the folder in your code editor. I use VS Code, so I just enter the following command.
在您的代码编辑器中打开文件夹很有用。 我使用VS Code,因此只需输入以下命令。
code .
Once the editor has opened, back in the terminal start the app with the following command
打开编辑器后,在终端中使用以下命令启动应用程序
npm run serve
Then open a browser and navigate to the URL that the app says it is running on. In my case that is http://localhost:8080/
然后打开浏览器并导航至该应用程序正在运行的URL。 在我的情况下是http://localhost:8080/
You should see the default Vue app in your browser.
您应该在浏览器中看到默认的Vue应用。
Create a new file /src/components/Header.vue
with the following code.
使用以下代码创建一个新文件/src/components/Header.vue
。
Dev Tweets
Rename /src/components/HelloWorld.vue
to Tweets.vue
, open the renamed file and replace the contents as below. (we will come back to this file shortly)
将/src/components/HelloWorld.vue
重命名为Tweets.vue
,打开重命名的文件并替换如下内容。 (我们将很快返回此文件)
Open the file /src/App.vue
this file provides the layout for our app. We import the two components above and tell Vue where to display them and I also add a sprinkling of tailwind CSS classes. Update the code in App.vue
as below.
打开文件/src/App.vue
此文件提供了我们应用程序的布局。 我们导入了上面的两个组件,并告诉Vue在哪里显示它们,我还添加了一些顺风CSS类。 如下更新App.vue
的代码。
That is the basic structure of the app complete.
这是完整的应用程序的基本结构。
Now I will get the Tweets
component talking to the WebSocket Server and displaying the incoming tweets. Open /src/components/Tweets.vue
and update it as per the code below.
现在,我将使Tweets
组件与WebSocket服务器通信并显示传入的Tweet。 打开/src/components/Tweets.vue
并按照以下代码进行更新。
Realtime Dev Tweets
{
{ tweet.user.screen_name }}
{
{ tweet.text }}
{
{ tweet.user.friends_count }} Following
{
{ tweet.user.followers_count }} Followers
In data()
I have created two variables, tweets
which will hold the tweets received in an array and connection
which will hold the WebSocket connection object.
在data()
我创建了两个变量, tweets
将保存在数组中接收的tweet, connection
将保存WebSocket连接对象。
In mounted()
I connect to the WebSocket server and set up an onmessage
event. This is triggered whenever the server broadcasts data. When the event is triggered the function converts the data to a JSON object with JSON.parse()
and pushes it to the top of the tweets array
using unshift
.
在mounted()
我连接到WebSocket服务器并设置onmessage
事件。 只要服务器广播数据,就会触发该事件。 触发事件时,该函数使用JSON.parse()
将数据转换为JSON对象,并使用unshift
将其推入tweets array
的顶部。
If the tweets
array contains more than 20 tweets, the last tweet in the array is removed using pop()
如果tweets
数组包含20条以上的tweets,则使用pop()
删除数组中的最后一条tweet
The onopen
event is for debugging and simply logs to the console one time when the client establishes a connection with the server
onopen
事件用于调试,仅在客户端与服务器建立连接时一次登录控制台。
The component template
loops through each tweet
held in tweets
and lays them out as a list. Each tweet includes a plethora of data. I’m pulling just a few items from each tweet screen_name
, profile_image
, text
, followers
, and following
.
该组件template
循环遍历每个tweet
举行tweets
,并奠定了出来作为一个列表。 每条推文都包含大量数据。 我从每个tweet的screen_name
, profile_image
, text
, followers
和following
仅提取了一些项目。
If you look at the app in your browser you will see the tweets scrolling through the page in real-time as the good people on twitter send them.
如果您在浏览器中查看该应用程序,则推特上的好人会发送这些推文,从而实时地滚动推文。
Try sending a tweet that includes one or all the words javascript
, nodejs
, or python
and watch your browser as appears a few seconds later. Feel free to mention me @simonstweet
along with a link to this article.
尝试发送包含一个或所有单词javascript
, nodejs
或python
的推文,然后在几秒钟后观察您的浏览器。 随时提及我@simonstweet
以及本文的链接。
Docker化每个微服务 (Dockerising each microservice)
As the saying goes (in the UK at least), “there’s more than one way to skin a cat”. I am going to use docker because I believe that’s the best approach for a number of reasons. This is not a docker tutorial, however. If you have not used Docker before you might feel a little overwhelmed, I know I was the first time I came across it. There are a lot of resources on the internet that provide great introductions to docker, YouTube might be your best bet initially.
俗话说(至少在英国),“有不只一种给猫皮剥皮的方法”。 我将使用docker,因为出于多种原因,我认为这是最好的方法。 但是,这不是docker教程。 如果您在还未感到不知所措之前没有使用过Docker,那么我知道我是第一次接触它。 互联网上有很多资源可以为docker提供出色的介绍,YouTube最初可能是您最好的选择。
If you don’t have Docker installed, you take a look at the Docker official website.
如果您尚未安装Docker,请访问Docker官方网站。
我将采取的方法 (The approach I will take)
There are a number of different options for deploying containers
部署容器有很多不同的选择
I am going to go with the simplest approach in this tutorial, which is to host them on my dev laptop.
在本教程中,我将采用最简单的方法,即将它们托管在我的开发笔记本电脑上。
The process will be
该过程将是
- Some small changes to each microservice to make them Docker friendly 对每个微服务进行一些小的更改以使其对Docker友好
- Create a Docker image for each container 为每个容器创建一个Docker映像
- Create a docker-compose file that builds containers from each image and configures them to talk to each other over the Docker network stack. 创建一个docker-compose文件,该文件从每个映像构建容器,并将其配置为通过Docker网络堆栈彼此通信。
创建Docker映像 (Creating the Docker images)
Python Twitter Client
Python Twitter客户端
Open a terminal and navigate to your python twitter client folder, for me that is /microservices/twitter_client
打开一个终端并导航到您的python twitter client文件夹,对我来说是/microservices/twitter_client
Create a new file called requirements.txt
in the root of the folder. Our Docker container will be running Python 3 and will have PIP available. When we create a container from the Docker image, PIP will use the requirements.txt file to make sure the required dependencies are installed. In our case that is python-dotenv
, tweepy
, and websocket
在文件夹的根目录中创建一个名为requirements.txt
的新文件。 我们的Docker容器将运行Python 3,并将提供PIP。 当我们从Docker映像创建容器时,PIP将使用requirements.txt文件来确保已安装所需的依赖项。 在我们的例子中是python-dotenv
, tweepy
和websocket
Add the following lines to requirements.txt
将以下几行添加到requirements.txt
python-dotenv
tweepy
websocket-client
Create a new file called Dockerfile
and add the code below
创建一个名为Dockerfile
的新文件,并在下面添加代码
FROM python:3
Add twitter_client.py /
Add requirements.txt /
RUN pip install -r /requirements.txt
CMD [ "python", "./twitter_client.py" ]
Environment Variables
环境变量
Before we create a Docker image from the Dockerfile, we need to tell Docker how to access the environment variables for the Twitter API. There’s also a problem with the URL to the WebSocket server, it’s hardcoded in twitter_client.py
This is an issue because each docker container is a self-contained system in its own right, so localhost refers to that container. I need to provide a way to tell the Docker container the address of the WebSocket container. I will do that later in a file called docker-compose.yml. For now, I need the Python script to be able to access the environment variables that will be in the docker-compose file.
在根据Dockerfile创建Docker映像之前,我们需要告诉Docker如何访问Twitter API的环境变量。 WebSocket服务器的URL也存在问题,它在twitter_client.py
中进行了硬编码。这是一个问题,因为每个Docker容器本身就是一个独立的系统,因此localhost指的是该容器。 我需要提供一种方法来告诉Docker容器WebSocket容器的地址。 稍后我将在名为docker-compose.yml的文件中进行此操作。 现在,我需要Python脚本才能访问docker-compose文件中的环境变量。
Open twitter_client.py
in your editor and make sure the code is updated as below.
在编辑器中打开twitter_client.py
,并确保代码更新如下。
import tweepy
from dotenv import load_dotenv
import os
from websocket import create_connection
import json
load_dotenv()
ws = create_connection(os.environ["WEBSOCKET_SERVER_URL"])
auth = tweepy.OAuthHandler(os.environ["TWITTER_API_KEY"], os.environ["TWITTER_API_SECRET_KEY"])
auth.set_access_token(os.environ["TWITTER_ACCESS_TOKEN"],
os.environ["TWITTER_ACCESS_TOKEN_SECRET"])
api = tweepy.API(auth)
class TwitterListener(tweepy.StreamListener):
def on_status(self, status):
ws.send(json.dumps(status._json))
print(status._json)
twitterListener = TwitterListener()
myStream = tweepy.Stream(auth=api.auth, listener=twitterListener)
myStream.filter(track=['javascript', 'nodejs', 'python'])
Notice the os.environ[]
, it provides access to the environment variables that will be stored in the docker-compose file.
请注意os.environ[]
,它提供对将存储在docker-compose文件中的环境变量的访问。
For now, I’m just going to build the image from the Dockerfile by running
现在,我将通过运行Dockerfile来构建映像
docker build -t microservices_twitter_client .
The above command tells Docker to create a new image called microservices_twitter_client
, the .
at the end tells Docker it can find the Dockerfile
in the current folder.
上面的命令告诉Docker创建一个名为microservices_twitter_client
的新映像.
最后告诉Docker它可以在当前文件夹中找到Dockerfile
。
2. Websocket Server
2. Websocket服务器
In the terminal navigate to the folder holding the code for the Websocket server. For me that’s /microservices/websocket_server
在终端中,导航到保存Websocket服务器代码的文件夹。 对我来说就是/microservices/websocket_server
Create a new file called Dockerfile
. Just like before we will define the Dockerfile image for this microservice in a Dockerfile and add the following code.
创建一个名为Dockerfile
的新文件。 就像之前一样,我们将在Dockerfile中为此微服务定义Dockerfile映像,并添加以下代码。
FROM node:12-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY app.js .
EXPOSE 8088
CMD [ "node", "app.js" ]
In this Dockerfile, I am using Node version 12 as the base image for the container. The command WORKDIR
create a new directory /app
in the image and tells Docker to use this as the working directory (base directory) for all further commands. So where you see ./
actually refers to /app
在此Dockerfile中,我将使用节点版本12作为容器的基本映像。 命令WORKDIR
在映像中创建一个新目录/app
,并告诉Docker将其用作所有其他命令的工作目录(基本目录)。 所以您看到的./
实际上是指/app
I then use COPY
to copy any files starting with package
and ending with .json
into the working directory. Then RUN
npm install which will install all the dependencies for our application. Once the install is complete COPY
app.js into the working directory.
然后,我使用COPY
将所有以package
开头并以.json
结尾的文件复制到工作目录中。 然后RUN
npm install,它将安装我们应用程序的所有依赖项。 安装完成后,将COPY
app.js COPY
到工作目录中。
Line 11, makes port 8088 available to be mapped to the outside world, so other containers or apps can connect to the WebSocket server. You will see how that is used later when we create a docker-compose.yml
file that will define the application stack.
第11行使端口8088可以映射到外界,因此其他容器或应用程序可以连接到WebSocket服务器。 您稍后将看到在我们创建定义应用程序堆栈docker-compose.yml
文件时如何使用它。
Finally, on line 13, I tell Docker to run the command node app.js
最后,在第13行,我告诉Docker运行命令node app.js
You can now build this image so it’s available to use later with
您现在可以构建此图像,以便以后可以使用
docker build -t microservices_websocket_server .
3. VueJS Application
3. VueJS应用
In a terminal navigate to your VueJS application folder. For me that is /microservices/twitter_ui
在终端中,导航到您的VueJS应用程序文件夹。 对我来说就是/microservices/twitter_ui
.dockerignore file
.dockerignore文件
As part of the docker build
command I will run npm install
this will create the node_modules
folder inside the container and ensure it has the latest updated dependencies. As such I don’t want the node_modules
folder on my development machine copying into the container. This is acomplished by creating a .dockerignore
file and listing the files that we want Docker to ignore.
作为node_modules
docker build
命令的一部分,我将运行npm install
它将在容器内创建node_modules
文件夹,并确保它具有最新的依赖关系。 因此,我不想将开发机器上的node_modules
文件夹复制到容器中。 这是通过创建.dockerignore
文件并列出我们希望Docker忽略的文件来完成的。
Create a new file in the root of the application folder and call it .dockerignore
it only needs one line adding to it.
在应用程序文件夹的根目录中创建一个新文件,并将其.dockerignore
,只需添加一行即可。
node_modules
Environment variables in VueJS
VueJS中的环境变量
With frontend Javascript apps we have to consider that the app is running in the browser rather than on the server. The implications of this are that environment variables on the server are not available to the app running in the browser.
对于前端Javascript应用程序,我们必须考虑该应用程序正在浏览器中运行,而不是在服务器上运行。 这样做的含义是服务器上的环境变量对于浏览器中运行的应用程序不可用。
Our app currently has a hardcoded URL to the WebSocket server. The best practice with VueJS is to create a .env
file in the root of the application for variables our application needs access to. There is a lot more to .env files when you get into the details of different environments such as Dev, Test, PreProd, and Prod. We will keep it simple here and just create a single .env file.
我们的应用程序当前具有WebSocket服务器的硬编码URL。 VueJS的最佳实践是在应用程序的根目录中为应用程序需要访问的变量创建一个.env
文件。 当深入了解不同环境(例如Dev,Test,PreProd和Prod)的详细信息时,.env文件还有很多其他内容。 我们将在这里保持简单,仅创建一个.env文件。
In the root of the VueJS application create a file called .env
在VueJS应用程序的根目录中,创建一个名为.env
的文件
Add this single line of code to the file.
将此单行代码添加到文件中。
VUE_APP_WEBSOCKET_SERVER_URL=ws://192.168.30.100:8088
Now open Tweets.vue
which is located in /src/components/Tweets.vue
现在打开Tweets.vue
它位于/src/components/Tweets.vue
Replace ws://localhost:8088
with process.env.VUE_APP_WEBSOCKET_SERVER_URL
when you're done the whole line should look like this
完成后,将ws://localhost:8088
替换为process.env.VUE_APP_WEBSOCKET_SERVER_URL
,整个行应如下所示
this.connection = new WebSocket(process.env.VUE_APP_WEBSOCKET_SERVER_URL);
Creating the Dockerfile
创建Dockerfile
Create a new file in the root of the application folder called Dockerfile
and add the code shown below.
在应用程序文件夹的根目录中创建一个名为Dockerfile
的新文件,并添加以下代码。
FROM node:12-alpine
RUN npm install -g http-server
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . ./
RUN npm run build
EXPOSE 8080
CMD [ "http-server", "dist" ]
This Dockerfile is similar in structure to the others. A key difference here is that to deploy the application into production, we need to first build it. The process creates a index.html
file that contains references to minified javascript. That index.html file needs to be made available via a webserver. We could have set up a NGINX server container, but a simpler approach for this use case is to install an npm package http-server
which I do on line 3.
该Dockerfile在结构上与其他类似。 这里的主要区别在于,要将应用程序部署到生产环境中,我们需要先对其进行构建。 该过程将创建一个index.html
文件,其中包含对精简javascript的引用。 该index.html文件需要通过网络服务器提供。 我们可以设置一个NGINX服务器容器,但是这种用例的一种更简单的方法是安装一个npm包http-server
,我在第3行中做了。
Following that, I go through a similar process as I did for the NodeJS WebSocket server. Once the files have been copied into the container, I build the application with npm run build
. This creates a dist
folder to hold all the build files.
之后,我将执行与NodeJS WebSocket服务器类似的过程。 将文件复制到容器后,我将使用npm run build
应用程序。 这将创建一个dist
文件夹来保存所有构建文件。
Finally, I run the http-server
and tell it to serve the dist
folder.
最后,我运行http-server
并告诉它服务dist
文件夹。
将所有内容与docker-compose文件一起拉 (Pull everything together with a docker-compose file)
If you don’t have docker-compose installed (it does not come with docker) you can visit https://docs.docker.com/compose/install/ to find out how to install it on your OS.
如果您没有安装docker-compose(它不是docker附带的),则可以访问https://docs.docker.com/compose/install/以了解如何在操作系统上安装它。
Finally, we are almost done, just one last thing to do before we start our Microservices application stack.
最后,我们差不多完成了,只是启动微服务应用程序堆栈之前要做的最后一件事。
We need a way to tell Docker what that stack comprises of, the relationship between each of the containers and the configuration for each container, i.e. Environment variables and what port each container should expose to the outside world.
我们需要一种方法来告诉Docker堆栈由什么组成,每个容器与每个容器的配置之间的关系,即环境变量以及每个容器应向外界公开的端口。
Create another folder in the microservices folder at the same level as twitter_client
, twitter_ui
, and websocket_server
folders. Name it docker
.
在微服务文件夹中与twitter_client
, twitter_ui
和websocket_server
文件夹处于同一级别创建另一个文件夹。 将其命名为docker
。
Navigate into the new Docker folder and create a new file called docker-compoes.yml
and add the following code. Take care to maintain the correct indentation. yml files are sensitive to an indentation that is not consistent.
导航到新的Docker文件夹并创建一个名为docker-compoes.yml
的新文件,并添加以下代码。 注意保持正确的缩进。 yml文件对不一致的缩进敏感。
version: "3"
services:
websocketserver:
image: microservices_websocket_server:latest
ports:
- 8088:8088
twitterclient:
image: microservices_twitter_client:latest
depends_on:
- websocketserver
environment:
- WEBSOCKET_SERVER_URL=ws://websocketserver:8088
- TWITTER_API_KEY=
- TWITTER_API_SECRET_KEY=
- TWITTER_ACCESS_TOKEN=
- TWITTER_ACCESS_TOKEN_SECRET=
twitterui:
image: microservices_twitter_ui
depends_on:
- websocketserver
ports:
- 8080:8080
The docker-compose file lists the services
that I want to run in this stack.
docker-compose文件列出了我要在此堆栈中运行的services
。
I have created three services
我创建了三个服务
- websocketserver 网络套接字服务器
- twitterclient 微博客户端
- twitterui 微博
Docker runs it’s own internal network and assigns it’s own IP Addresses internally. The service names are also essentially hostnames for each service on the docker network and will map to an IP Address inside docker.
Docker运行自己的内部网络,并在内部分配自己的IP地址。 服务名称本质上也是docker网络上每个服务的主机名,并将映射到docker内部的IP地址。
You can see that I make use of this on line 12
where I set the value for the environment variable WEBSOCKET_SERVER_URL
to ws://websocketserver:8088
您可以看到我在line 12
上利用了该line 12
,在这里我将环境变量WEBSOCKET_SERVER_URL
的值设置为ws://websocketserver:8088
Environment variables for the Twitter App are set in the twitterclient
service. You can get these from the Twitter developer's website and the App that you created earlier.
Twitter应用程序的环境变量在twitterclient
服务中设置。 您可以从Twitter开发人员的网站和您先前创建的应用程序中获取这些内容。
We also have some dependencies in our stack. Both the VueJS App and the Python Twitter Client, rely on the WebSocket server being up and running before they start. If this wasn’t the case, there would be no server for them to connect to.
我们的堆栈中也有一些依赖项。 VueJS App和Python Twitter Client都依赖于WebSocket服务器在启动之前已启动并正在运行。 如果不是这种情况,将没有服务器可供他们连接。
You can see that each service has an image. You should recognize this as the image we created when we ran docker build for each of our services.
您可以看到每个服务都有一个图像。 您应该将其识别为我们为每个服务运行docker build时创建的映像。
Finally the websocketserver
and the twitterui
both require that their internal ports be made available outside the container. This is achieved by mapping export_port
: internal_port
In this case, both internal and external ports are the same, but they don’t have to be and often are not.
最后, websocketserver
和twitterui
都要求它们的内部端口在容器外部可用。 这可以通过映射export_port
: internal_port
来实现,在这种情况下,内部和外部端口都是相同的,但是不必相同,通常也不相同。
运行堆栈 (Running the stack)
In order to make sure that everything is running correctly I will first run the stack in what is called attached
mode. This means the stack will only be available for as long as the terminal is open. This is not ideal for production use, but for testing it means I get to see any errors that might be generated. I also still have the console.log
statement logging to the console, which will help me know that everything is working.
为了确保一切正常运行,我将首先以所谓的attached
模式运行堆栈。 这意味着堆栈仅在终端打开时才可用。 对于生产用途而言,这不是理想的选择,但是对于测试而言,这意味着我可以看到可能产生的任何错误。 我也仍然有console.log
语句记录到控制台,这将帮助我知道一切正常。
Run the following command in the terminal in the docker
folder, the same folder that contains the docker-compose.yml
file.
运行在终端中的以下命令在docker
文件夹时,包含在同一文件夹docker-compose.yml
文件。
docker-compose up
After a few seconds and if everything went well, you should see tweets in the form of JSON scrolling up the terminal.
几秒钟后,如果一切顺利,您应该会看到JSON形式的推文,将终端向上滚动。
Now open your browser and visit http://localhost:8080
You should see tweets streaming into the app in real-time.
现在,打开浏览器并访问http://localhost:8080
您应该看到实时流向应用程序的推文。
If you now go back into the terminal and hit Ctrl+c, this will shut down the stack. Now run the stack again detached mode using the -d
switch
如果现在返回终端并按Ctrl + c,将关闭堆栈。 现在使用-d
开关再次运行堆栈分离模式
docker-compose up -d
Once the stack is running, you will be back at the terminal and the stack will be running in the background.
堆栈运行后,您将回到终端,并且堆栈将在后台运行。
You can see which containers are running by issuing the command
您可以通过发出以下命令查看正在运行的容器
docker ps
If you need to shutdown the stack when in detach mode, open a terminal, make sure you're in the same folder as your docker-compose.yml
file and issue the command
如果在分离模式下需要关闭堆栈,请打开终端,确保与docker-compose.yml
文件位于同一文件夹中,然后发出命令
docker-compose down
结论 (Conclusion)
I have covered a lot in this article and there is much that I missed. Some important best practices are missing but would have diverted from the concept I was trying to put across.
我在本文中介绍了很多内容,而我却错过了很多。 缺少一些重要的最佳实践,但它们会偏离我试图提出的概念。
In summary, though, you have seen how it is possible to stream real-time from Python into VueJS. You have also learned about how to deploy a WebSocket server, which is the central technology that glues this stack together.
总而言之,您已经了解了如何从Python实时流式传输到VueJS。 您还了解了如何部署WebSocket服务器,这是将此堆栈粘合在一起的核心技术。
You also saw how you can create Docker containers for apps and use docker-compose to define and create application stacks.
您还了解了如何为应用程序创建Docker容器以及如何使用docker-compose定义和创建应用程序堆栈。
I hope you enjoyed this article, I enjoyed writing it.
希望您喜欢这篇文章,也喜欢撰写它。
Please leave comments below if you are struggling or let me know if you think there is a better way of achieving anything that I discussed here.
如果您正在苦苦挣扎,请在下面留下评论;如果您认为有更好的方法可以实现我在这里讨论的任何事情,请告诉我。
翻译自: https://medium.com/swlh/developing-a-full-microservices-application-stack-5c9fe14c870f
vuejs和nodejs