大纲:

1、本篇关键技术点及其释义

2、实际需求和目标

3、可行的三大解决方案

4、微服务与传统服务的差别

5、代码大纲:安装依赖及nameko五个完整的代码示例

6、附录:docker的在线安装方式


本篇技术关键词:

nameko、rabbitMQ、rpc、swagger、flask,gevent、WSGI

其中nameko是python的微服务框架。

rabbitMQ作为消息中间件,用于服务注册。

rpc用于微服务之间通信。

swagger用于API描述。

flask是python中轻量级Web框架。

gevent+WSGI是利用协程解决web服务高并发问题。


需求和目标:

各个算法模块独立开发,彼此之间代码独立开发,独立部署(也就是可以部署在不同机子上)。

每个算法模块都以微服务的方式进行注册管理。

最终对外发布的服务只有一个,也就是只占用一个端口资源。

算法模块对于整体对外发布的服务实现可插拔。

增加或者减少算法模块对Web端基本无影响,即不用修改多少代码即可正常投入使用。

另外,需要同时支持定时离线更新模型和实时在线训练的效果。


实际可行的解决方案:

由于算法模块都是python开发的,因此解决方案有以下几种:

1、使用传统主流微服务框架,比如以java语言开发的Dubbo、spring cloud等框架

因为使用的是Java的微服务框架,

那么就需要考虑将python微服务作为异构服务融入到Java微服务框架体系中去。

也就需要将python微服务与服务注册中心做结合,

传统的注册中心比如Zookeeper,Eureka和Consul。

可以说,无论是使用dubbo java栈还是使用SpringCloud全家桶,都是比较完善健全的。

但另一方面,这就意味着需要有Java后端开发,python算法端开发以及python粘合端开发。

即便以python为主语言的算法工程师可以干后两者内容,但仍少不了需要java开发工程师配合。

2、使用k8s对容器化部署的服务进行统一管理

因为k8s具有自己的一套体系,包括服务注册,服务发现,负载均衡,健康检测,资源管理,扩容,pipeline管理,以及日志管理等。

可以说,它也有自己的一套比较健全的大工具箱,可以通过自己组装来完成整个闭环的打造。

正因为容器化部署,以及k8s等的健全快速发展。

也反过来影响到java的微服务框架开始往下一代基于k8s的微服务体系框架Istio发展。

可以说,使用k8s这一套对微服务进行管理,是目前的一个发展趋势,它开始脱离了语言本身的限制,关心更多的也是服务级别的内容。对于python而言,是一个比较好的选择。

但另一方面,k8s大而全,也就意味着需要投入足够的人力去做相关的开发。

比如说,每一个人都去负责一到两块内容,这样才能比较全面地发挥出它相应组件对应的功效。那么此时,如果算法工程师想靠自己一个人负责除了前端外的完整链路,可以说很难,也很耗费精力,整体开发的周期也会比较长。

3、使用python自己的微服务框架nameko

nameko是python自己的微服务框架,它本身没有java语言下Spring Cloud、Dubbo等微服务框架体系来得完整和专业。

但对于微服务的常规需求基本都可以满足,比如服务注册,服务发现等等。

最大的好处是:足够轻量,算法工程师可以自己一条龙干到底,代码的绝对掌控。也就是所谓的一人独挑大梁。那种自己一个人就能把所有事都干了的感觉,简直不能更快乐。

本文提供nameko的实现方式。

若想看需求和目标对应的直接解决方案。

则可以略过前面代码示例,直接看最后一个。

若想简单学习了解一下nameko的一些操作流程,能整体接收更顺滑则可以顺序观看。

另外,关于算法模块和服务发布模块,比如通过容器化部署作资源隔离,多机多端口部署并用ng做负载,及反向代理发布对外服务,以及使用redis做简单服务查询缓存等等,不在本文讨论范畴。

其相关内容和本文实现的并不冲突,属于完整闭环上不同工作环节上的内容,可以同时使用。


微服务与传统服务的差别:

1、微服务和服务最大的区别在于各模块的解耦,使得模块之间独立性强,更轻量。

比如前后端都有各自的服务,但是前后端分离,那么就可以各自独立开发,独立部署,独立排查问题。耦合性低,独立可用性强。

而当系统复杂时,单独的后端也会特别沉重,往往需要多个人同时开发,为了实现类似和前后端分离的这种解耦效果,所以就会每个人独立开发各自模块。

传统模块开发是使用相同语言,各自开发,遇到相互调用的地方,则通过模块化引包调用。

而微服务,则将各个模块进行微服务化。

模块之间可以通过restful api、Message Broker以及rpc等方式进行通信调用。

从而更加通用灵活,每个模块的独立性更强,甚至可以使用不同的语言进行开发。

各自开发也更加轻量。

2、易维护,易管理,高可拓展。

每个微服务独立开发,不会产生牵一发动全身的影响,拓展也会更容易。

其次如果每个模块都进行服务化,那么一来很占用端口资源,二来服务混乱,不容易管理。

而微服务可以通过一个统一的注册中心进行注册,统一的管理中心进行管理。就会具备更好地拓展性。并且不影响最终对外的服务发布,即便增加一个微服务,对已有服务也不会有影响,使得服务模块的拓展变得更高效可拓展。


代码大纲

因代码涉及较多,故简单罗列代码示例对应大纲:

示例一:flask + nameko + rabbitMQ + 单模块 + 临时性建立rpc通道

1、通过nameko管理微服务。

2、通过flask部署发布服务,flask中会封装调用微服务。

示例二:flask + nameko + rabbitMQ + swagger + 单模块 + 临时性建立rpc通道

1、通过nameko管理微服务。

2、通过flask部署发布服务,flask中会封装调用微服务。

3、swagger管理api文档说明可视化。

示例三:flask + nameko + rabbitMQ + swagger + 单模块 + 永久性建立rpc通道

1、通过nameko管理微服务。

2、通过flask部署发布服务,flask中会封装调用微服务。

3、swagger管理api文档说明可视化。

示例四:flask + nameko + rabbitMQ + swagger + 多模块 + 永久性建立rpc通道

1、通过nameko向rabbitmq注册多个微服务。

2、不同模块组成的微服务之间进行彼此间的通信。

3、flask最终对外发布服务,并调用nameko管理微服务。

4、swagger进行api文档可视化。

适用场景:python不同功能模块之间的协调开发

示例五:flask + nameko + rabbitMQ + swagger + 多模块 + 永久性建立rpc通道 + 订阅发布模式

1、发布多个微服务,实现订阅发布的模式。

2、发布方给订阅方数据,订阅方接收到数据后做相应的处理。

3、发布方数据生成有两种方式,一种是定时生成数据,进行发布。

另一种是从服务接收数据,进行发布。

4、订阅者一旦发现有数据,立即进行消费,并存储结果。

5、Web端实现两个接口,一个是直接获取最新的自动产生的结果。

另一个是主动传输数据给发布方,并从对应的订阅方获取结果。

适用场景:不同算法模块独立开发,并同时支持实时在线预测和定时离线预估。

附上代码地址:

https://github.com/sunjianzhou/nameko_test

有帮助的请给颗star。


依赖安装:

一、安装nameko库

pip3 install nameko

二、安装及启动RabbitMQ

1、拉取官方镜像

docker pull rabbitmq:management

2、启动容器

docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq:management

备注:这里前提是先安装了docker,docker安装相关,可以看附录。

启动后可以在浏览器中访问 http://localhost:15672 ,如果能够使用 guest:guest 验证信息登录 RabbitMQ 的控制面板,说明它已经在你的开发环境中运行起来了。


示例一:flask + nameko + rabbitMQ + 单模块 + 临时性建立rpc通道

1、通过nameko管理微服务。

2、通过flask部署发布服务,flask中会封装调用微服务。

1、vim helloworld.py

2、运行服务

3、命令行客户端

进入nameko交互模式

这里的nameko_service是上面自己定义的name

而hello则是上面用rpc装饰了的函数名

4、在flask中调用微服务

vim flask_call_nameko.py

这里有两点要注意,

第一:CONFIG需要和RabbitMQ的配置保持一致。

可以通过执行nameko shell看到连接的是哪个。

第二:使用rpc调用的时候务必要名字对应上,这里是通过ClusterRpcProxy来完成关联的。

关联主要靠nameko中的名字,该nameko中的函数名。

这里的nameko_service是上面定义的name是一致的。

这里的hello是上面对应nameko中的rpc装饰过的函数名。

然后,这里的

rpc.nameko_service.hello(name=name)

是一种同步调用的方式,也就是会等待执行结束返回结果。

rpc也有异步调用的接口,按如下方式即可变成异步调用。

 result_async = rpc.nameko_service.hello.call_async(name=name)

此时,因为属于异步调用,所以不会等待结果返回,而直接执行后面语句。

但在调用result_async.result()时则会等待异步任务返回结果。

注意:异步调用的结果只能在语句块内获取,即调用 .result() 等待结果。语句块之外连接断开就无法获取了。

5、启动flask服务

python3 flask_call_nameko.py

6、调用启动的flask服务。

这里可以用浏览器,也可以用postman,也可以用rest_client,也可以用curl。

因为涉及到post请求,所以可以使用curl和postman都简单试一下。

get请求

curl效果:

这里执行是在另外一个节点上执行的。

postman效果:

post请求

curl效果:

postman效果:

小结:

nameko实现的服务都是作为扩展内容的形式实现的。

可以说nameko实现的内容存在于服务代码之外,可以随时插入到服务中,也可以从服务中拔掉。

所以nameko可以起多个模块,实现各自的微服务内容,然后统一注册到一个固定的地方,从而可以供其他人消费。

这里用的是RabbitMQ,也就是说RabbitMQ充当了一个池子,nameko作为生产者往里输送内容,而真正发布的flask服务则作为消费者,从RabbitMQ里进行消费。

所以只要RabbitMQ是分布式部署的,那么模块的开发即部署就可以是分布式的。也就能灵活地进行资源模块化分配。

通过这种方式,RabbitMQ统一管理所有的微服务,然后对外发布的服务也只需要一个即可。

干净,整洁,并且被统一管理,然后RabbitMQ还有自己的管理界面。


示例二:flask + nameko + rabbitMQ + swagger + 单模块 + 临时性建立rpc通道

1、通过nameko管理微服务。

2、通过flask部署发布服务,flask中会封装调用微服务。

3、swagger管理api文档说明可视化。

1、vim helloworld.py    稍微丰富一点点,多一个类

2、通过nameko启动服务

注意:

这里执行了nameko run helloworld,相当于此时启动了微服务,并且连接到了rabbitmq。

因为是直接控制台执行,所以相当令该队列进行了常驻。

服务会暂时一直存在于该队列中,故而可以多次消费。

如果将该命令进行退出,那么后面flask启动的服务则无法从队列中消费到微服务,因为没有注册的微服务。

当然,这个注册过程可以放到后台去运行。

3、可以继续使用nameko shell简单测试一下

4、flask中调用微服务

vim flask_call_nameko.py

和前面的例子相比,这里多了一些注释。

然后用Swagger对app进行了包装。

这里的注释需要有一定的格式规范。

另外,也可以通过swag_from装饰器的方式,来对说明文档进行文件化。

只是这里实验没成功,就没去细究问题了。后续有需要再去调研相关内容。

主要是yml格式,具体可参考

官网说明https://swagger.io/docs/specification/describing-parameters/

如果对于写swagger语法格式想要边写边看效果的话。

则可以使用Swagger_Editor这个在线编辑工具。

一种类似于markdown的工具,可以实时查看代码效果。

Swagger在线编辑器

http://editor.swagger.io/#/

swagger的主要作用是,让文档说明可以直接在url上进行界面化显示。

减少额外的api说明开销。

这里的服务启动依然是使用异步协程方式,目的是为了支持高并发。

5、启动服务

python3 flask_call_nameko.py

6、查看服务接口是否ok

这里就直接使用postman来进行简单测试

先看get请求结果:

再看post请求效果:

7、然后再看看swag的效果:

这里对应的swag网址是http://:/apidocs/

故而直接打开http://:8001/apidocs/

这里的是自己部署服务的节点ip。

具体还能点开展示细节:

点击try it out还可以通过界面获得实际返回效果。

不再需要额外整理API文档,前端也可以提前看到效果,并简单测试。


通过上述几个示例我们可以发现,我们可以通过

ClusterRpcProxy(config)对nameko进行rpc的连接。

通过with语句,可以及时地创建和关闭,从而避免资源一直被占用,导致浪费。

需要注意的是, 运行

ClusterRpcProxy(config) 时会创建与rabbitMQ的连接,该操作比较耗时,如果有大量的微服务调用,不应该重复创建连接,应在语句块内完成所有调用。

实际上通过flask使用时,可以使用 flask_nameko。

但要注意,

不要在视图函数里实例化ClusterRpcProxy(config)。

否则每个用户的每次请求都会重新创建销毁与队列的连接,比较耗时。

示例三:flask + nameko + rabbitMQ + swagger + 单模块 + 永久性建立rpc通道

1、nameko管理微服务。

2、flask发布服务,flask中会封装调用微服务。

3、swagger管理api文档说明可视化。

与前两个示例的区别在于本示例减少资源开销,适用于真实服务开发。

1、模块微服务化独立开发

vim hello_world.py

2、通过nameko,将微服务注册到rabbitMQ中

如果有多个,则依次执行即可,可以都放到后台去。

3、开发flask服务,对微服务进行统一管理调用

4、启动flask服务并使用postman进行简单测试

看根服务

看get请求接口

看post请求接口

swagger界面这里就不再展示了。


示例四:flask + nameko + rabbitMQ + swagger + 多模块 + 永久性建立rpc通道

1、通过nameko向rabbitmq注册多个微服务。

2、不同模块组成的微服务之间进行彼此间的通信。

3、flask最终对外发布服务,并调用nameko管理微服务。

4、swagger进行api文档可视化。

与前面三个示例相比,当前示例是针对多个微服务之间的开发。

并且不同微服务之间存在通信,相对于真实开发已初具雏形。

适用场景:

python不同功能模块之间的协调开发

1、开发多个模块,彼此之间相互通信

vim module_one.py

vim module_two.py

第一步,写两个模块,彼此之间相互通信

实际上,可以看到,两个模块除了自己的名字和要连接的目标rpc不一样外,其他内容都一样。

name是为了让其他微服务能定位到你

rpc是为了让其他微服务可以访问到你的函数

故而这里就可以通过

connection_rpc.get_personal_info的方式来访问到对方的函数。

这里和咱们正常的模块调用区别在哪呢?

最大的区别就是,现在这两个模块可以在不同的物理机上部署,只需要使用的同一个rabbitMQ就可以了。

而rabbitMQ是可以分布式部署的。

所以区别就很明确了,这种访问方式对代码的部署要求性更低。大家可以自行开发各自模块。

实际上,同一个模块中不同的类之间也可以通过微服务的方式进行调用。即添加上rpc装饰器即可。

当然,代码都在一起,你直接使用正常的本地调用方式也ok。

但有一点要注意的是,要注册成微服务的模块,必须要对应有类。

2、通过nameko,分别将各模块内容注册到rabbitMQ当中

这里是开启的两个客户端

现在两个模块各自开发好了

需要通过nameko将两个模块都注入到rabbitMQ中去,也就是类似于一个集中的服务注册中心,从而可以被其他人所消费。

这里可以看到,两个微服务都起来了,并且已经连接到同一个mq上去了。

3、通过flask部署发布服务,调用微服务的功能函数。

vim flask_call_nameko.py

创建app,并建立rpc通道的永久性连接。

使用Swagger对app进行封装。

get_apis函数只是为了做连通性测试。

hello这个函数则是开始访问我们前面通过nameko运行起来的微服务模块了。

这里逻辑也很简单,根据名字访问不同的微服务模块。

都是访问对应微服务模块里的communication方法。

4、启动flask服务并通过postman进行测试

而在客户端我们可以分别看到两次的调用输出。

然后会发现每个微服务各自也会有自己的日志信息。

这是因为我们在各自的微服务端都有自己的打印输出。

但是这些输出并不会在flask服务端打印出来。

故而这里可以做到日志的清晰简洁。

哪里出错,就去哪里查看具体日志进行定位。

那么这段代码基本功能就完整了。

回过来我们再看看需求。

比如我们有多个算法模块或者python功能模块要开发。

我们就可以各个算法模块进行独立开发。

然后每个模块都各自注册到rabbitMQ当中,作为微服务存在。

不同模块之间可以存在通信,当然,也可以没有通信。

但真正对外发布的服务,只会有一个,其端口资源,也只会占用一个。

我们去访问服务的时候,主要就通过rpc通信的方式去访问各个模块对应的结果。

然后对于前端而言,因为我们写了API规范,前端也可以直接看我们swagger在线接口。

并且,还能直接在上面测试各种返回。


不同微服务之间可以进行调用,也可以进行发布-订阅。

生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列,谁先抢到消息谁就会从队列中取走消息;即对于每个消息只能被最多一个消费者拥有。

发布者订阅者模式:发布者生产消息放到队列里,多个监听队列的消费者都会收到同一份消息;即正常情况下每个消费者收到的消息应该都是一样的。

示例五:flask + nameko + rabbitMQ + swagger + 多模块 + 永久性建立rpc通道 + 订阅发布模式

1、发布多个微服务,实现订阅发布的模式。

2、发布方给订阅方数据,订阅方接收到数据后做相应的处理。

3、发布方数据生成有两种方式,一种是定时生成数据,进行发布。

另一种是从服务接收数据,进行发布。

4、订阅者一旦发现有数据,立即进行消费,并存储结果。

5、Web端实现两个接口,一个是直接获取最新的自动产生的结果。

6、另一个是主动传输数据给发布方,并从对应的订阅方获取结果。

适用场景:不同算法模块独立开发,并同时支持实时在线预测和定时离线预估。

实际场景:

现在有多个算法模块,每个算法模块都以微服务的方式注册到RabbitMQ中。

微服务通过nameko进行统一管理,并实现订阅发布的模式。

即发布方会维护一个topic和算法模块的对应关系。

接收到参数数据后会发送至对应的topic里去。

而各个算法模块作为订阅者会实时去自己对应的topic池里查看,一旦发现来了一批参数,那么进行算法模型的调用,并得到预测结果,并存储起来。

这里发布方接收数据有两种方式,

一种是定时离线接收数据。

一种是实时在线接收数据。

无论哪种方式,一旦发布了数据,就会被订阅者,也就是对应的算法模块消费掉。

Web接口有两个,一个是获取定时训练的模型结果。

另一个是实时传入数据,然后去对应的订阅方(算法模块侧)直接获取结果。

进一步通过流程图来描述实际场景:

实时在线推理测通过前端接收到数据,或者是上传csv文件,或者是读指定数据库数据,然后通过web接口去实时预测,获得当前数据对应结果。

而定时离线推理则是通过定时主动去读取数据库或者hdfs的数据,然后通过web接口直接去获取最新结果。

那这里web服务端主要就做两件事,一个是对应实时在线推理的。

接收到主题以及对应的参数数据信息,发布到订阅池里去,然后拉取结果。

另一个是对应定时离线预测的,直接拉取最新结果。

然后订阅池子里定义好算法模块对应主题,一旦接收到某个主题的数据参数,就往这个主题里扔。

然后算法模块因为绑定了这个主题,就会及时感知到数据。

所以一有数据,算法模块端就可以进行消费,然后将结果存储起来。

然后Web端就可以直接去获取结果。

这里用订阅发布的好处是:

1、订阅方,也就是算法模块只关心输入输出。

也就是你给我输入,我给你输出。

而不需要关心输入是怎么来的。

2、发布方任务明确,就是将主题对应的数据参数发布到订阅池中对应的主题中去。

这里包括在线数据和定时数据。

3、Web端定位也明确,给定主题和参数,就能获得结果。

所以每一块内容开发功能定位都很明确,也可以独立开发。

为避免前面存在没看导致跳跃太大,这个示例注释会相对完善一些。

1、实现一个数据生产者,具备定时获取数据,和外部接收数据的功能,并实时发布到相应主题里。

vim module_producer.py

这里主要通过dispatch来进行数据发布,发布到对应主题上。

类属性name是作为微服务的名字,用于被其他微服务调用时的一个重要标识。

添加rpc则是为了能够让其他注册到RabbitMQ里的微服务可以调用到本服务的对应函数。

producer使用了timer进行装饰,目的是为了周期性获取数据,并调用发布函数。这里的数据简单的自己随机生成。

get_data_from_web则是通过外部web请求,经过flask后调用的接口。

也就是传进来任务id,对应主题(即要调的算法应用场景),以及相应的信息(可以改成关键字参数,即模型参数)。进行相应场景的主题发布。

2、实现两个消费者模块,可以理解为两个算法模块,用于接收对应主题的数据并消费数据,产生结果。

先是第一个消费者模块

vim moduler_consumer_one.py

这里使用类属性的字典和列表分别用于存储实时在线请求和定时离线预估的结果。

RpcProxy只是为了不同微服务之间的通信,获取对方的一些内容信息,但前提是也得用rpc进行装饰。

talk_to_producer主要是和生产者做连通性测试使用。

event_handler装饰器主要用于订阅信息使用,参数对应为微服务名字,以及其发布的某个主题。

函数参数payload则是从订阅的主题里获得到的内容。获取到数据后则可以开始进行自己的相应处理。

这里除了一个订阅了topic_one还订阅了一个public_topic主题的内容。

主要是为了区分公共主题和私人主题。

但实际上私人主题订阅可以进一步完善,比如可以添加一些类似用户检验,安全认证等以确保用户有私人主题访问权限的内容。

这里订阅到信息后,会先去check有没有任务id,因为这里任务id是唯一区分实时在线任务和定时离线任务的标识,并且两个任务对应的结果存储方式不同。

read_data是使用rpc装饰,故而是为了让其他微服务或rpc通信机制能够获取并调用该函数内容。

该函数主要功能根据task_id是否为空判断任务类型,然后根据任务类型进行结果的获取。

再是第二个消费者模块

vim moduler_consumer_two.py

这个模块的功能和消费者一基本一致。

主要即获取数据,进行消费,也有自己订阅的私人主题(对应特定应用场景),以及公共主题(对于一些公共多模型可以共用的场景)。

然后通过read_data函数进行对应结果的获取。

3、通过nameko启动以上发布模块以及两个订阅者模块

先启动发布方的模块

再启动两个订阅方的模块

这里可以看到,由于我的发布数据方有一个十秒间隔自动发布数据。

启动后,发布方一经发布,订阅方就各自有接收到数据并消费打印出日志了。

当然,在实际开发中,我们可以写到固定的日志文件中去。

4、使用轻量级Web框架flask进行服务端内容开发

vim flask_web.py

这里引入了Swagger,用于API的可视化展示

引入了FlaskPooledClusterRpcProxy,用于Web中的rpc代理使用

Flask与request用于简单的web接口开发

WSGI和gevent用于异步请求的高并发

monkey则用于打补丁,让协程可以更全面地感知IO操作,遇到则进行切换,提高并发能力,thread=False则是为了防止阻塞到其他的线程和进程操作,彼此不影响。

create_app用于创建app,并做简单配置,最主要的是NAMEKO_AMQP_URI的地址配置。

这个和nameko运行的地址保持一致。

使用Swagger对app进行封装,并注册到rpc代理中。

然后对rpc通道进行一次连接。

这个连接可以理解为类似mysql数据库表的链接。

这里直接建立永久性链接是因为链接会有开销,每次调用服务再链接会导致资源开销太大,也会影响速度。

get_apis是为了方便简单测试当前Web是否work的get接口。

这是一个GET请求接口。

绑定在call_service_auto函数上。

主要用于获取定时离线预测的最新结果。

根据给定的topic进行获取。

另一个POST请求接口,需要传入topic以及相应的message。

接收到信息后,自动生成一个唯一编码,并将参数通过rpc访问的方式,传输给发布者。

发布者再根据主题发布相应的消息到对应主题上。

然后对应主题的订阅者模块订阅到消息后进行消费,并保存到自己对应的字典中。

最后服务端再直接去对应的订阅者端获取结果。

主函数则通过WSGI对app进行封装,然后发布服务。

5、启动flask服务,并通过postman查看效果

调用get接口,获取topic_one的最新消息

调用get接口,获取topic_two的最新预测结果

调用post接口,获取topic_one对应的实时预测结果

调用post接口,获取topic_two的实时预测结果

6、再看看swagger的效果,浏览器输入:8001/apidocs/并回车,其中ip是对应本地可访问到的部署服务器ip

整体上,API描述信息,也都能看得了。简单明了。

到这里基本功能框架雏形就搭好了。

若按此方式进行开发则可以进行内容整改和丰富了。

本篇内容也就告一段落了。


附录:

关于docker在线安装:

1、安装依赖包

yum install -y yum-utils device-mapper-persistent-data lvm2

2、配置stable镜像仓库

yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

注:镜像源可以自己选择,前两个慎选,速度会很慢。

1、官方源:https://download.docker.com/linux/centos/docker-ce.repo2、微软源:https://mirror.azure.cn/docker-ce/linux/centos/docker-ce.repo3、清华源:https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo4、阿里源:https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

3、启动edge和testing镜像仓库(这步操作可选)

yum-config-manager --enable docker-ce-edgeyum-config-manager --enable docker-ce-testing

4、更新yum软件包索引

yum makecache fast

5、查看docker CE可选版本

yum list docker-ce.x86_64  --showduplicates | sort -r

6、安装指定版本docker CE(这个版本可以自行选择)

yum install docker-ce-18.03.1.ce-1.el7.centos

7、启动docker

systemctl start docker

8、验证docker是否安装成功

docker run hello-world

更多文章请关注

centos部署python flask_python 微服务框架之nameko实践相关推荐

  1. 熔断降级与限流在开源SpringBoot/SpringCloud微服务框架的最佳实践

    目录导读 熔断降级与限流在开源SpringBoot/SpringCloud微服务框架的最佳实践 1. 开源代码整体架构设计 2. 微服务逻辑架构设计 3. 微服务熔断降级与限流规划 3.1 微服务熔断 ...

  2. python rpc微服务框架_grpc的微服务探索实践

    对于微服务的实践,一般都是基于Java和Golang的,博主最近研究了下基于Python的微服务实践,现在通过一个简单的服务来分析Python技术栈的微服务实践 技术栈:Python3 + grpc ...

  3. Centos部署Spring cloud微服务(CCE example)

    前提 您登录的用户必须拥有 sudo 权限. tomcat版本:v9 jdk版本1.8 tomcat镜像地址:http://archive.apache.org/dist/tomcat/tomcat- ...

  4. Java 云原生微服务框架 Quarkus 入门实践

    点击上方"芋道源码",选择"设为星标" 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | ...

  5. 微服务(三):python微服务框架有哪些?

    python中的微服务框架有Istio.Dubbo和nameko三种 1.Istio Istio是一个用来连接.管理和保护微服务的开放平台,使用Istio可以建立已部署服务网络,且Istio具备负载均 ...

  6. python微服务框架_微服务架构框架有哪些?常用微服务架构介绍

    小伙伴们知道常用的微服务架构框架有哪些吗?上回我们介绍了一些常用的微服务架构设计模式,这次我们就来了解一下一些常用的微服务架构框架吧. 一.Dubbo Dubbo框架是由阿里巴巴开发的开源式的分布式服 ...

  7. python 微服务框架_Python微服务架构chili_chicken

    ### chili_chicken是什么 现在微服务架构大火,企业项目纷纷向微服务转变.Python目前处于稳步发展的状态,用于多领域,比如人工智能.爬虫.运维.web等,我们此贴只讨论web方向.现 ...

  8. python-37-python微服务框架Nameko

    Python微服务框架nameko的简单使用 推荐一款 Python 微服务框架 - Nameko 微服务框架有Istio.Dubbo和nameko三种: 一.Istio Istio是一个用来连接.管 ...

  9. python 微服务框架 知乎_序: 我需要一个什么样的微服务框架

    前言 新坑第一篇文章, 做一个开篇的序吧. 开发了很多 python 的 web 微服务, 也使用过很多 web 框架, django, tornado, flask, 等等等等. 不同的 web 框 ...

最新文章

  1. 新手初学Regular Expression正则表达式--快速入门
  2. SAP RETAIL 特征参数文件(Characteristic Profile) II
  3. js ie 6,7,8 使用不了 firstElementChild
  4. Eclipse报错:this compilation unit is not on the build path of a java project
  5. python中类的使用_Python第九课-使用 类(class)创造新的数据类型!
  6. VB:读取及设定NumLock/CapsLock/ScrollLock的值
  7. HTTPS SSL/TLS协议原理
  8. VMware下Ubuntu与宿主Windows共享文件夹
  9. iPhone 真机调试应用程序
  10. 前端开发和后端开发究竟有什么区别?详细介绍
  11. C51红外接收与发射控制及原理编码与解码
  12. 大数据与数据挖掘的基本概念,它们之间的内在联系是什么?
  13. html之div中id和class的区别
  14. 猜数字游戏,用户充值版(Java)
  15. 社群空间站一键发布微信群精品优质社群的搜索和发布平台源码
  16. NDN Link :利用区块链技术代替TCP/IP 通信模式
  17. PCI Express 协议基础
  18. 不用中间变量交换两个数的值
  19. 基于matlab的数字下变频器的设计与仿真应用,基于matlab的简单数字下变频器的设计...
  20. g723源码详细分析(-)

热门文章

  1. 韦博英语危机爆发,教培行业如何应对中年危机?
  2. 0118互联网新闻 | 抖音成央视春晚独家社交媒体传播平台;石墨任务清单小程序上线...
  3. 风靡硅谷营销界的 MarTech 魔术
  4. 浅析Python中深拷贝和浅拷贝
  5. Python进阶【第七篇】文件处理
  6. 企业选择做网站托管服务的几大因素
  7. 前台后台进程转换问题
  8. Google Analytics虚拟页面和事件追踪的区别
  9. sql语句的一些参考
  10. SAP数据表(一)商品表