记录MindSphere On Cloud Foundry的一次尝试过程
试验背景:
开始时间:2019年12月11日
结束时间:2019年12月13日
最后一次更新:2020年4月30日(问题三)
自己编写一个后台程序,尝试推送到Cloud Foundry上,并开放从MindSphere以外访问的权限。
程序实现以下功能:
1、使用MindSphere提供的API获得指定时序的Token
2、启动定时任务,从时序数据中拉取数据,并打印在日志中。
3、提供一个REST接口,用来获取数据。
4、程序开启log日志,打印到Cloud Foundry的容器中。
前提条件:
1、电脑已经安装Power Shell。
2、提前编写好要测试的程序。
3、拥有MindSphere的Developer账号。
操作随记:
(一)编写程序
程序地址:https://github.com/quchunhui/demo-macket/tree/master/mindsphere
(二)登陆Cloud Foundry
Cloud Foundry的登陆,可以参考上一篇博客。
命令:cf login -a https://api.cf.cn1.mindsphere-in.cn --sso --skip-ssl-validation
博客地址:https://www.cnblogs.com/quchunhui/p/12015167.html
(三)创建CF空间并赋予权限
1、切换到已有组织(org),相关命令如下:
切换组织:cf target -o rexelcn0
2、创建测试程序的运行空间(space),相关命令如下:
创建空间:cf create-space rexel-mf-api-test
查看所有空间:cf spaces
3、更新空间的Role(角色)及Permission(权限),相关命令如下:
查看Space中的使用者及其权限:cf space-users rexelcn0 rexel-mf-api-test
附加:
如果希望使用其他账户完成后续的操作,可以使用一下命令来添加权限。
为指定用户添加SpaceManager权限:cf set-space-role chunhui.qu@rexel.com.cn rexelcn0 rexel-mf-api-test SpaceManager
为指定用户添加SpaceDeveloper权限:cf set-space-role chunhui.qu@rexel.com.cn rexelcn0 rexel-mf-api-test SpaceDeveloper
(四)将应用程序部署到Cloud Foundry
1、在程序根目录中创建manifest.yml文件
文件内容如下:
1 2 3 4 5 6 7 | --- applications: - name: rexel-mindsphere-api- test instances: 1 random-route: true path: target /rexel-mindspere-api-0 .0.1.jar memory: 512M |
2、将程序推送到CF的空间,相关命令如下:
跳转入Spaces:cf target -s rexel-mf-api-test
跳转到程序根目录:cd D:\MyWork\22_Github\rexel-cn\rexel-jarvis\rexel-mindsphere-api
程序打包:mvn package(注意,如果程序修改了,一定要重新打包,因为cf push上传的jar包,不是源代码,这一点非常重要。)
推送程序:cf push
列出所有应用及运行状态:cf apps
查看应用的详细状态:cf app rexel-mf-api-test
【小插曲1】
执行cf push的时候报错一个错误
在程序根目录中使用mvn package重新编译打包,然后再次执行cf push之后问题解决。
【小插曲2】
程序上传之后,cf提示启动失败
按照提示的命令查看了日志。命令:cf.exe logs rexel-mindsphere-api-test --recent
可以看到提示内存不够。
尝试将manifest.yml中配置的内存大小调高,重新推送之后解决。修改之后的manifest.yml文件内容
1 2 3 4 5 6 7 | --- applications: - name: rexel-mindsphere-api- test instances: 1 random-route: true path: target /rexel-mindspere-api-0 .0.1.jar memory: 1G |
(五)SSH进入到空间查看运行
官网操作手册:https://developer.mindsphere.io/zh/paas/paas-cloudfoundry-ssh.html
1、检查空间SSH是否开启
命令:cf space-ssh-allowed rexel-mf-api-test
2、开始指定空间SSH权限:
默认是开启的,如果没有开启,可以使用以下命令打开权限。
命令:cf allow-space-ssh rexel-mf-api-test
3、为应用开启SSh权限:
命令:cf enable-ssh rexel-mindsphere-api-test
注意不要弄错了空间名(rexel-mf-api-test)和应用名(rexel-mindsphere-api-test)
4、重新启动应用:
命令:cf restart rexel-mindsphere-api-test
5、SSH进入应用空间:
命令:cf ssh rexel-mindsphere-api-test
6、进入日志所在路径:
在spring程序的logback中,配置的日志路径为:/home/vcap/logs
进入路径:cd /home/vcap/logs/
7、查看日志是否正常:
命令:less rexel-md-test2019-12-11.log
(六)将程序注册到MindSphere
1、使用MindSphere账号登录
2、选择Developer Cockpit(开发驾驶舱)
3、选择仪表盘选项卡。
4、单击创建新的应用。
类型:Standard
基础设施:MindSphere Cloud Foundry。
显示名称:Rexel MindSphere Api Test(字面上容易理解的就可以)
内部名称:rexelmfapitest(这将会为成为应用URL的一部分。初始化创建后,内部名称不能被更改!)
版本:1.0.0(MindSphere 支持 Major.Minor.Patch 方案。版本必须以 >=1 的主号码开头。保存之后版本不能被更改。)
应用图标:随便上传一个就可以。我用了一个钢铁侠第一任人工智能助理Jarvis的图片。
输入组件名称。 示例应用的组件名称为hello-spring-cloud。
组件名称
组件名称必须与 manifest.yml 中的 Cloud Foundry 应用名称匹配。否则,生产系统中的自动注册将会失败。
组件名称:rexel-mindsphere-api-test(必须与 manifest.yml 中的 Cloud Foundry 应用名称匹配。否则,生产系统中的自动注册将会失败。)
Cloud Foundry URL:rexel-mindsphere-api-test-comedic-hippopotamus-vl.apps.cn1.mindsphere-in.cn(使用 cf app {app_name} 来获取您部署的应用的 URL。)
端点:为您的组件添加至少一个端点。使用 /** 来匹配您应用的所有路径。
1 2 3 4 5 | 关于端点: 您可以为端点使用任意路径。 不允许使用 /api ,因为这是为从相对路径(例如 /api/iot/v3/timeseries )调用 MindSphere api 预留的。 避免使用keywords,因为这是为 SQL 操作预留的。 您可以使用通配符。 * 匹配路径中任何字符,** 匹配任何字符和子路径。 |
点击保存。将被重定向到应用详细信息。 应用程序处于In-Development状态,并且准备好注册了。
可以看到应用创建成功。(有没有开心的感觉?)
【小插曲】
保存失败,因为说明中不能使用中文。
使用有道词典,将中文翻译成应为,重新搞一次解决。
(七)配置应用角色和范围
参考官网资料:https://developer.mindsphere.io/zh/howto/howto-cf-running-app.html
1、切换到授权管理选项卡。
2、选择应用。
3、创建一个应用范围并选择分配给哪个角色。
关于角色和范围:https://developer.mindsphere.io/zh/concepts/concept-roles-scopes.html
这里暂时只赋予一个权限mdsp:core:iot.timUser(读取时间序列的权限)
(八)注册应用
1、切换到仪表盘选项卡,打开应用详细信息,单击注册。
(九)分配应用角色
1、从Launchpad 中打开 Settings 应用,并切换到角色选项卡。
2、选择一个应用角色并单击编辑分配。
分配一个或多个用户到应用角色。
结束编辑。登出 MindSphere 并重新登陆。
(十)授权管理
使用密钥管理器API授权您的应用访问其他租户数据。该操作主要针对某个应用需要访问其他不同租户的数据的情形,例如,在没有用户交互的情况下频繁进行数据处理时。
1、在 MindSphere Launchpad Developer/Operator Cockpit 授权管理应用凭证中,点击对应的 APP 名称,选择右侧签发访问权限
2、选择所需权限类别,并提交
3、将显示的对应信息保存,
注意:此信息只显示一次
注意:此信息只显示一次
注意:此信息只显示一次
4、将对应信息添加至应用 Manifest .yml 文件中,并重新上传应用
1 2 3 4 5 6 7 8 9 10 11 12 13 | --- applications: - name: rexel-mindsphere-api- test instances: 1 random-route: true path: target /rexel-mindspere-api-0 .0.1.jar memory: 1G env : HOST_ENVIRONMENT: cn1 MDSP_OS_VM_APP_NAME: rexelmfapitest MDSP_OS_VM_APP_VERSION: 1.0.0 MDSP_KEY_STORE_CLIENT_ID: <只显示一次的客户ID> MDSP_KEY_STORE_CLIENT_SECRET: <只显示一次的客户密钥> |
5、使用Postman测试是否部署成功
先使用 base 64 工具加密客户ID与客户秘钥,格式为客户ID:客户秘钥(半角符号)
工具地址:https://www.base64encode.org/
工具截图:
以获取Token为例,使用Postman测试一下:
请求类型:POST
请求地址:https://gateway.cn1.mindsphere-in.cn/api/technicaltokenmanager/v3/oauth/token
Header:
Body 选项卡设置格式为Raw ,格式为JSON,内容为:
1 2 3 4 5 6 | { "appName" : "rexelmfapitest" , "appVersion" : "1.0.0" , "hostTenant" : "rexelcn0" , "userTenant" : "rexelcn0" } |
点击发送之后,可以看到已经可以正常获取Token信息
(十一)从外部访问应用程序提供的接口
与MindSphere的人员确认过了,目前暂不支持,直接从外部访问部署到MindSphere上的应用。
有两种方式进行应用落地:
方式一:
开发一整套的应用(包括前端和后端,比如Spring + Vue),推送到CF,并注册到MindSphere上。
这种方式的缺点是,必须拥有MindSphere账号的用户才有可能访问应用。
方式二:
在MindSphere之外,如阿里云上面开发独立的应用,通过MindSphere开放的API接口来获取数据,
这种方式的缺点是,需要独立服务器以及数据库等配套组件支撑。好处是与MindSphere解耦。
我尝试了第一种方式,自己写了一个最简单的页面(一个按钮,一个显示数据的文本框),尝试部署到MindSphere上。
(十二)部署并测试Web页面
写了一个最简单的web页面,部署的方式与Spring后台程序一样,
唯一需要注意的是manifest.yml的内容必须多一个而配置就是:buildpack: staticfile_buildpack_offline
用来告诉CF这是一个静态的文件。
那么,如何访问后台应用app中的接口呢?
将静态的页面推送上去之后,不管三七二十一,先访问一下后台试试(接口地址可能不对),结果从浏览器控制台上可以看到如下错误:
1 | Refused to connect to 'http://localhost:8081/rexel/timeseries/test' because it violates the following Content Security Policy directive: "default-src 'self' static.cn1.mindsphere-in.cn" . Note that 'connect-src' was not explicitly set , so 'default-src' is used as a fallback. |
问了相关技术人员,建议我去看一下MindSphere->Cockpit下的content-security-policy(内容安全策略),
MindSphere默认的CSP设置如下:
1 | default-src 'self' static.cn1.mindsphere- in .cn; style-src * 'unsafe-inline' ; script-src 'self' 'unsafe-inline' static.cn1.mindsphere- in .cn; img-src * data:; |
网上找了一些资料,对Content Security Policy这个词进行了快速扫盲,试图找到解决办法
网友博客:
https://www.jianshu.com/p/74ea9f0860d2
MindSphere官网介绍:
https://developer.mindsphere.io/zh/concepts/concept-csp.html#_3
https://developer.mindsphere.io/zh/howto/howto-csp.html
CSP官网:
https://content-security-policy.com/
首先,尝试了取消CSP的安全限制,将CSP的设置修改如下
1 | default-src 'self' *; style-src * 'unsafe-inline' ; script-src 'self' 'unsafe-inline' *; img-src * data:; |
然后界面返回了这么一个鬼东西,已经是完全懵逼状态,
1 | MindSphere Gateway error: A redirect is required to get the users approval |
问了一下西门子的朋友,说是每次修改DSP之后,MindSphere后台服务会重启,需要等十几分钟再登陆。
吃过午饭,回来重新试了一次之后,发现成功了,简直高兴的不得了。然而
【小插曲】
发现由于html里写的访问地址是localhost,刚好我电脑本地的后台程序也在运行中,
所以,访问的是我本地的程序,并不是注册在Cloud Foundry上的程序,白他妈的高兴一场,还兴奋的去和老板报了喜,
怎么办?自己挖的坑,哭着也得填完。
于是重新想西门子的售后发起求助,寻求解决办法。
最终,经过售后一顿猛如虎的操作之后终于解决。
解决办法:
地址1:http://localhost:8081/rexel/timeseries/test
地址2:https://rexelcn0-rexelmfapitest-rexelcn0.cn1.mindsphere-in.cn/rexel/timeseries/test
地址3:https://rexelcn0-rexelmfapitest-rexelcn0.cn1.mindsphere-in.cn/v1/rexel/timeseries/test
地址4:https://rexelcn0-rexelmfapitest-rexelcn0.cn1.mindsphere-in.cn/api/rexelmfapitest-rexelcn0/v1/rexel/timeseries/test
地址5:https://supplab-rexelcn0-staticweb-rexelcn0.cn1.mindsphere-in.cn-supplab.cn1.mindsphere-in.cn/api/rexelmfapitest-rexelcn0/v1/rexel/timeseries/test
地址6:/api/rexelmfapitest-rexelcn0/v1/rexel/timeseries/test
结果地址6最终生效,问题终于得以解决,吹出去的牛逼也算是能圆回来了,差点没让老衲圆寂在电脑前。
2020/4/22追记:
关于前端页面访问后端的地址,有一点需要注意:后端服务的注册版本对接口有影响。
如下图,我们的应用版本是纯数字,系统给的接口版本号是:大写的V1
如果应用版本不是数字,而是如v1.0.0这样的,系统给的接口版本是:小写的v1
(十三)注销应用
万事有始有终,应用可以正常使用了,现在开始尝试将一个应用注销。
先来回忆一下上线的步骤
1、在cf上创建org、space
2、赋予用户在space中的权限
3、将应用push到cf并启动
4、在ms(MindSphere的简称)上注册应用
5、赋予相应的角色和范围
所以,彻底下线应用的操作就应该和上面的相反,
不过个人认为,上面的第5步应该不需要执行,删除了应用按理说应该可以自动取消相应的授权、角色和范围。
所以,直接从上面的第4步开始,let's go go go......................
1、在ms上注销应用(这里注销的是一个以前测试的应用)
可以看到应用删除成功了
检查一下,是否按照我的猜想,授权、角色和范围都已经删除干净。
先检查一下授权:嗯,被删除的“myfirstapp”已经消失了。
再来检查一下角色和范围:很好,这里也被删的很干净。
2、从cf上停止并删除app
先检查一下空间。命令:cf spaces
我们要删除的应用在rexel-demo中。
进入到要删除的空间,命令:cf space rexel-demo
查看一下在空间中运行的应用,命令:cf apps
暂停应用。命令:cf stop rexel-mindsphere-api-test
删除应用。命令:cf delete cf stop rexel-mindsphere-api-test
重新查看是否已经删除。命令:cf apps
最后看到空间中已经没有任何app了,可以放心的删除空间了。
3、删除空间
删除空间。命令:cf delete-space rexel-demo
查看空间,确认是否成功删除。命令:cf spaces
(十四)Backing Services的创建及关联
官网地址:https://developer.mindsphere.io/zh/paas/index.html
1. 查看可用的Backing services:
命令:cf marketplace
会列出service的名字,不同套餐,及说明。具体套餐请参考官网介绍。
2.创建Backing services实例
命令:cf create-service elasticsearch5 elasticsearch-xs my-elasticsearch-service
3. 检查创建的serivce状态
命令:cf services
刚刚创建完成的状态:create in progress
过几分钟再次查看的状态:create succeeded
4. 把App与Service进行关联
命令:cf bind-service rexel-service my-elasticsearch-service
需要注意的是,需要等待service创建成功之后才可以进行关联,如果service处于创建中状态进行关联,会提示如下错误:
错误:An operation for service instance my-elasticsearch-service is in progress.
5.重新载入或重新启动应用
要使应用能够访问服务实例,请运行 cf restage
或 cf restart
来重新载入或重新启动应用。
命令:cf restart rexel-service
6.获取服务实例访问凭证
将服务实例绑定到应用后,Elasticsearch 数据库的凭证将存储在应用的环境变量中。运行 cf env APP-NAME
显示环境变量。
命令:cf env rexel-service
应用环境变量样例:(用户名,密码,端口等敏感字段均进行了修改脱敏)
System-Provided: { "VCAP_SERVICES": { "elasticsearch5": [ { "binding_name": null, "credentials": { "host": [ "http://eld521309a.service.dc1.a9ssvc:9213" ], "hosts": [ "eld55509a-es-0.node.dc1.a9ssvc" ], "password": "a9sa1d17b178af842aa1a2349474997dd67bf438a2b", "port": 9213, "scheme": "http", "username": "a9s76348fd458842b5234cc5e3f5ce46c3582a3e7c38" }, "instance_name": "my-elasticsearch-service", "label": "elasticsearch5", "name": "my-elasticsearch-service", "plan": "elasticsearch-xs", "provider": null, "syslog_drain_url": null, "tags": [ "searchengine" ], "volume_mounts": [] } ] } } { "VCAP_APPLICATION": { "application_id": "32309d25-88fb-4b5b-b16d-c449d1d7e1b9", "application_name": "rexel-service", "application_uris": [ "rexel-service-shy-mongoose-wj.apps.cn1.mindsphere-in.cn" ], "application_version": "fffa6fd1-b50d-4d6f-8ce4-c2f155600af5", "cf_api": "https://api.cf.cn1.mindsphere-in.cn", "limits": { "disk": 512, "fds": 16384, "mem": 700 }, "name": "rexel-service", "organization_id": "d36d5255-6364-4d96-bab1-c2d5a0ca760a", "organization_name": "tenant0", "process_id": "32309d25-88fb-4b5b-b16d-c449d1d7e1b9", "process_type": "web", "space_id": "b64f9b6c-b09f-42a4-a4b7-ebcb6b4d4167", "space_name": "rexel-ids", "uris": [ "rexel-service-shy-mongoose-wj.apps.cn1.mindsphere-in.cn" ], "users": null, "version": "fffa6fd1-b50d-4d6f-8ce4-c2f155600af5" } } User-Provided: HOST_ENVIRONMENT: cn1 MDSP_KEY_STORE_CLIENT_ID: rexelcn0-rexelservice-1.0.0 MDSP_KEY_STORE_CLIENT_SECRET: xxxxxxxxxxxxx MDSP_OS_VM_APP_NAME: rexelservice MDSP_OS_VM_APP_VERSION: 1.0.0 No running env variables have been set No staging env variables have been set
7.解绑服务实例
命令:cf unbind-service rexel-service my-elasticsearch-service
8.删除服务实例
命令:cf delete-service my-elasticsearch-service
查看一下服务实例状态。状态为:delete in progress
过几分钟,再次查看服务实例状态。可以看到服务实例已经被删除。
(十五)其他尝试
这部分后面有时间会继续补充
1、使用MindSphere的数据分析工具
2、使用MindSphere提供的后台服务(以Mongodb为例)
【总结】
1、MindSphere整个基于Cloud Foundry开展的,Cloud Foundry是业界第一个开源PaaS云平台,
整个验证过程一步一个坎,其根本原因是对Cloud Foundry的不熟悉,后续有时间需要多学习一下这个平台,
如果时间允许,最好自己安装部署一遍。
2、MindSphere的小白级的资料太少,如果是一点基础都没有的,很难顺利上手,
而且资料不是基于“用户场景”的,像我的这种尝试场景,需要各处去寻找资料,知识也连不起来。
对使用者来说不是很友好。
附:其他可能遇到的问题
【问题一】
错误日志:
1 | You have exceeded your organization's memory limit: app requested more memory than available |
问题原因:
每个org都有内存等限制,超过org的内存限制就会出现这个问题。
查看Org的内存限制
查看org详情。命令:cf org rexelcn0
查看org的配额。命令:cf quota cf-quota-1552463110231
注意应用的内存大小不要超过这个限制就可以。
我尝试着将org中没有用到的空间给删除掉,重新push了一次应用。
【问题二】
问题描述:
想ssh进入应用,查看一下运行状态,应用是重新部署上去的,结果提示以下错误。
1 | Error opening SSH connection: ssh : handshake failed: ssh : unable to authenticate, attempted methods [password none], no supported methods remain |
检查了space和app对ssh的支持状态都没有问题。
问题原因:
修改了app的ssh权限之后,需要重新启动一下app,否则权限不会生效。
解决办法:
重启app。命令:cf restart rexel-mindsphere-api-test
ssh进入app。命令:cf ssh rexel-mindsphere-api-test
【问题三】
问题描述:
前端页面中嵌入了地图,结果在显示的时候一直报错
Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Centent Security Policy directive: 'self' 'unsafe-inline' static.cn1.mindsphere-in.cn"
解决办法:
在应用的内容安全策略(CSP)中增加unsafe-eval。
default-src 'self' *; style-src * 'unsafe-inline'; script-src * 'self' 'unsafe-inline' 'unsafe-eval'; img-src * data:;
附:角色范围整理
附:CF操作命令:
http://cli.cloudfoundry.org/zh-Hans/cf/
--END--
解绑服务实例¶
运行 cf unbind-service
可以解除应用与服务间的绑定关系。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)