vuejs和nodejs_将Python,NodeJS和VueJS部署为微服务

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,并将它们整合到微服务架构中。

3 Microservices 3种微服务

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。

  1. In your browser navigate to https://developer.twitter.com/. If you don't already have one register an account.

    在浏览器中,浏览至https://developer.twitter.com/ 。 如果您还没有人,请注册一个帐户。

  2. After logging in, click on Developer portal

    登录后,单击Developer portal

  3. Hover your mouse over your username and from the dropdown menu, click Apps

    将鼠标悬停在用户名上方,然后从下拉菜单中单击Apps

  4. Click Create App and fill in the form you're presented with.

    点击Create App然后填写显示的表单。

  5. Once your app is created, you can retrieve your API credentials. There are two sets of credentials Consumer API keys and Access token & Access token secret. You will need both sets of keys shortly for use in the Python App.

    创建应用后,您可以检索API凭据。 有两组凭据( Consumer API keysAccess 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.StreamListeneron_status方法简单地打印接收到的每个鸣叫的文本。 为了开始接收推文,我实例化了TwitterListener,创建了一个新的流,然后添加了一个过滤器以仅接收包含以下一个或所有以下值的推文: javascriptnodejspython

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 wsmodule

输入以下命令以安装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 + PrettierESLint + 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

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并按照以下代码进行更新。




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_nameprofile_imagetextfollowersfollowing仅提取了一些项目。

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.

尝试发送包含一个或所有单词javascriptnodejspython的推文,然后在几秒钟后观察您的浏览器。 随时提及我@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)

  1. 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-dotenvtweepywebsocket

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_clienttwitter_uiwebsocket_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.

最后, websocketservertwitterui都要求它们的内部端口在容器外部可用。 这可以通过映射export_portinternal_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

你可能感兴趣的:(python)