• [介绍/入门] 一站式容器化部署商城 Magento产品介绍
    产品描述版本: 1.9类型: 电子商务华为移动互联解决方案提供了一种一站式基于容器集群管理部署Magento商城的方法。Magento被认为是全球范围内最实用、最完整的电子商务网站架构系统,是国际化电子商务解决方案之一。它支持多种语言、多个商铺平台统一管理,具有丰富的模块化架构体系以及丰富的拓展功能。它专业的开源性,使其在第三方系统集成方面有着极为良好的表现。套餐设计之初考虑了配置的优化。在一定范围内可供用户按需调整。 Magento产品特点1、促销及市场营销工具高度灵活的优惠券规则设定(价格规则),能够对特定的会员级别、时间期限、分类目录及产品进行设定规则。支持层级价格,可设定对特定用户组的优惠价格,或购买一定数量产品后获得批发价格。同一个产品可设置多个层级价格。支持将产品信息通过电子邮件发送给好友功能,有两种模式:仅供登录用户使用或所有访客使用。 2、买家分类目录浏览支持分类目录下或搜索结果中的分层导航/分面导航,即通过商品属性方便地筛选所需商品。例如同时要求价格区间,颜色和款式等筛选条件,网店将列出符合条件的商品。支持产品按列表形式或网格形式展示实时切换功能。灵活的商品高级搜索功能,商家可以设定可供买家选择的搜索字段,例如价格、性别、颜色、货号等。 3、买家商品页面浏览支持商品多图片查看,具备图片放大功能。支持产品评论评级功能。支持交叉销售模块,追加销售模块,相关商品模块及最近浏览过的商品模块。 4、结算流程一页式超快速结算,无需页面跳转。无需注册即可购买结算/支持访客结算。支持多地址结算功能,一个订单中的多个商品可分别制定配送地址。 5、配送运输同一定订单可提供多种运输方式供买家选择。支持有条件的免运费功能。支持根据目的地、重量和商品数量计算运费功能。 6、支付方式同一定订单可提供多种支付方式供买家选择。可扩展至支持微信支付和支付宝以及银联支付在线支付 。 7、买家帐号管理支持实时订单状态追踪和历史查询。支持从帐号管理界面中直接生成重复订单(提升多次相似下单效率)。帐号概览支持快速产看以下项目:最近订单,个人信息,邮件广告简报订阅状态,默认账单地址,默认货运地址,购物车状态,意愿清单状态,最近订购商品,最近查看产品,最近添加的标签。 8、商品目录管理支持商品批量导入和导出,通过CSV文件进行批量产品管理,可通过此途径直接将商品关联至分类目录。支持商品展现形式(例如颜色,尺码等),可自选商品(例如Dell勾选配置自定义电脑)及组合商品(例如西装三件套)发布。 9、订单管理支持后台查看,编辑以及直接创建填写订单。支持电话中心订单创建功能。支持创建新客户,选择特定客户并查看其当前购物车状况,意愿清单,最近订单项,以及商品比较清单,查看地址,发送折扣券以及给予特价优惠。 10、客户服务支持联系我们网站邮件发送功能。支持买家和后台管理员密码遗忘邮件取回功能。管理员可创建自定义的全套客服邮件。 11、分析和报告支持销售平台全局快速报告功能。支持弃置购物车中商品报告功能。支持浏览最多商品报告功能。支持购买最多产品报告功能。 12、搜索引擎优化支持URL地址重写功能实现URL完全控制。支持所有页面的Meta信息控制。 13、支持国际化电子商务支持多语言,买家可方便地切换语言。支持多币种,买家可方便地切换币种。商家设置转换汇率,并基于此计算网店所显示的价格及买家所需支付费用。支持paypal访客付款即信用卡付款模式,paypal账户付款模式,paypal一键购买模式。
  • [资料下载] 6月10日 华为云技术私享会武汉站-Kubernetes 容器与微服务加速应用云化
    本帖最后由 橘色西瓜 于 2018-6-13 17:37 编辑活动已经顺利结束,为了方便大家回顾下载当天私享会的会场资料,小编汇总整理当天资料,待补充内容后续再补充,持续刷新中~~ 欢迎大家阅读下载。 2018年6月10日议题: ServiceStage-让企业应用上云更加简单,运营更高效 讲师:PaaS高级解决方案经理/吴方杰 源于开源,高于开源,Kubernetes全栈容器技术剖析 讲师:华为云应用服务产品经理/江舒杭 快人一步,华为云新一代分布式缓存Redis(DCS2.0) 讲师:PaaS高级解决方案经理/吴方杰 华为微服务架构转型实践之路 讲师:华为云微服务产品经理/蒋鸿伟 华为云立体运维 讲师:华为云运维服务产品经理/徐博 演讲材料合集请见附件: 17260
  • [资料下载] 【资料下载】2018华为云技术私享会深圳站-微服务与kubernetes加速应用云化
    本帖最后由 橘色西瓜 于 2018-5-22 11:47 编辑15775 活动已经顺利结束,为了方便大家回顾下载当天私享会的会场资料,小编汇总整理当天资料,待补充内容后续再补充,持续刷新中~~ 欢迎大家阅读下载。 2018年5月19日议题: Kubernetes全栈容器技术剖析 讲师:PaaS高级解决方案经理/毛雪鹏 PDF下载:15752 华为云新一代分布式缓存Redis(DCS2.0) 讲师:华为PaaS中间件域产品经理/赵娟 PDF下载:15753 华为云立体运维 讲师:华为PaaS高级工程师/闫硕 PDF下载: 15754 使用码云+华为云快速构建微服务应用 讲师:码云负责人/周凯 PDF下载: 15755 无“微”不至,华为微服务产品与实践分享 讲师:华为微服务平台高级架构师/李勇军 PDF下载: 15756
  • [资料下载] 【资料下载】2018华为云技术私享会南京站- 华为云应用服务&DevCloud技术介绍与实践
    本帖最后由 橘色西瓜 于 2018-5-22 11:48 编辑15776 活动已经顺利结束,为了方便大家回顾下载当天私享会的会场资料,小编汇总整理当天资料,待补充内容后续再补充,持续刷新中~~ 欢迎大家阅读下载。 2018年5月16日议题: DevCloud之聊聊代码提交那些事 讲师:华为云软件开发云高级产品经理/庄表伟 PDF下载: 15747 ServiceStage-让企业应用上云更简单,运行更高效 讲师:华为云PaaS解决方案架构师/诸旻 PDF下载: 15748 Serverless产品及相关应用场景介绍 讲师:华为云PaaS服务Serverless产品经理/胡桂兵 PDF下载: 15749 华为微服务架构转型实践之路 讲师:华为云PaaS服务微服务产品经理/刘云华 PDF下载: 15750 华为云立体运维 讲师:华为云PaaS服务运维产品经理/徐博 PDF下载:15751
  • [资料下载] 【资料下载】4月26日 华为云技术私享会成都站-DevOps遇到微服务和容器
    14941 2018年4月26日议题: DevOps-软件研发效能提升之道 讲师:华为云DevCloud高级产品经理/瞿然 PDF下载:14942 视频回看:https://bbs.huaweicloud.com/videos/3bfca69135e24513a020c33ca4185a99 一站式微服务与云中间件实践分享 讲师:华为云PaaS高级架构师/黄靖凯 PDF下载:14946 视频回看:https://bbs.huaweicloud.com/videos/7b36dbca0189478792e5209fa4067210 揭秘Serverless与NoOps关键技术 讲师:华为云Serverless产品经理/胡桂兵 PDF下载:14945 视频回看:https://bbs.huaweicloud.com/videos/b764fa8932dd4f769388abeb3dab3dc7 Kubernetes全栈容器技术剖析 讲师:华为云PaaS高级解决方案经理/陈弘 PDF下载:14944 视频回看:https://bbs.huaweicloud.com/videos/008f94ee8d92485ba089b9ae3e4c27dc 基于容器部署的DevOps 讲师:华为云DevCloud高级产品经理/羊振华 PDF下载:14943 视频回看:https://bbs.huaweicloud.com/videos/10ea6b01a4b24149a1d6ba96e472f6fb
  • [技术干货] 华为云微服务引擎CSE大量新特性上线,诚邀您免费体验
    1、提供GO语言微服务开发框架SDK  支持插件化注册中心、多RPC协议(已默认实现http和highway,可扩展)  提供熔断降级、容错、路由管理、限流、错误注入、灰度发布等治理能力 2、提供Service Mesh商业版  支持.NET、Node.js、PHP等多语言应用微服务解决方案,能够以零侵入模式接入CSE微服务治理,提供完善的服务治理能力  兼容Dubbo协议,支持存量Dubbo应用零侵入接入CSE 3、提供网关服务EdgeService解决方案  支持Restful请求汇聚及转发,支持服务映射、请求解析、加密解密、鉴权等自定义能力  网关服务本身也可接入CSE进行微服务治理 4、提供微服务灰度发布能力  支持按照流量权重方式  支持按接口参数自定义灰度发布规则 5、微服务流水线能力增强  支持Java,GO、多语言Docker应用一键式构建和部署  流水线已支持对接Github和GitLab,Bitbucket、Gitee、DevCloud即将上线  支持一键式创建基于GoSDK或JavaSDK的微服务工程(自动生成框架代码、编译、构建、部署脚本和环境) 6、支持对接zipkin、Apollo、Prometheus  CSE集成了Zipkin提供自动调用链追踪能力,用户无需改动代码即可启用基于Zipkin和Java chassis 的分布式调用链追踪的功能  CSE支持对接不同的配置中心(CSE ConfigCenter、阿波罗) 立即体验:https://console.huaweicloud.com/cse/?region=cn-north-1#/cse/home 了解详情:https://www.huaweicloud.com/product/cse.html
  • [热门活动] 重磅惊喜!45万体验金人人有份,就在云容器引擎CCE训练营!
    本帖最后由 关羽夫人 于 2018-4-21 11:04 编辑司马懿问诸葛亮,依依东望你望的究竟是什么?原来望的就是——华为云 容器训练营。云容器引擎CCE自诞生以来就在使用说明、用户体验上狠下功夫,帮助中心、视频教程、云图说从未间断。然而所谓百闻不如一见,看教程哪有实践操作来得印象深刻。 4月23日,容器训练营正式上线,自己动手的机会来了!训练营提供初级、进阶案例,从创建集群到创建应用一应俱全,让想要体验容器的你快速玩转CCE。 看到这里,有些看过CCE教程的老朋友脑海中可能会闪过一条“温馨”提示: 14268 对,即便CCE是免费的,在使用过程中也会消耗基础设施费用。这条提示可以说是很贴心了,连充值按钮在哪儿都写得清清楚楚,看起来像诱惑程序猿的下班铃。 但是,今天的容器训练营不一样。 14267 容器训练营 完 全 免 费,我们的口号是“体验CCE,0元创集群”! 无论新老用户,只要是首次使用云容器引擎-训练营,都能领取150代金券,人人可享。 代金券使用无门槛,无需充值即可在训练营中0门槛体验CCE的高效快捷,亲身感受华为云容器技术的内在功力。 14269下面开始体验教程: 首先,您需要登录华为云控制台,并单击体验按钮,果断领取150元代金券,否则系统将判断您为土豪哦。 请戳链接https://console.huaweicloud.com/cce2.0/?region=cn-north-1#/app/guidance/list ,开始愉快创集群吧
  • [技术干货] 基于华为云的一个典型的持续部署方案
    本帖最后由 橘色祥云楼楼主 于 2018-4-20 14:52 编辑本文作者:乔雷 原华为PaaS架构师/系统和软件工程师,现Cloud BU中国业务技术支持部解决方案架构师 基于华为云的一个典型的持续部署方案:FunctionStage(Serverless)+(Monocular+)Helm Chart + CCE(Kubernetes+Docker) [*]1. 关于持续集成(CI)和持续部署(CD) [*]2. 一个华为云上的持续部署方案 [*]3. 部署截图 摘要:华为云迄今为止已经有14大类超过100种服务了,可以做很多有用和好玩的方案。本文以一个实际的案例,讲述如何使用华为云上的相关服务(主要是FuctionStage和CCE)完成自动化持续部署(CD,Continuous Deployment);并且通过Monucular手动部署Helm Charts打包的Kubernetes应用。这充分说明了华为云云容器引擎CCE支持和兼容开源生态Kubernetes以及在DevOps的强大能力,以及华为云支持业界主流自动化部署工具的能力。 1. 关于持续集成(CI)和持续部署(CD)在软件开发和运维领域,我们经常会听到很多概念,比如DevOps,持续集成(CI,Continuous Integration),持续交付(CD,Continuous Delivery),持续部署(CD,Continuous Deployment)等等。这些新的概念、方法论和工具的出现,主要是为了应对目前业务的挑战。主要是要求业务推出和运维即“快”又“稳”: [*]快:比竞争对手更快的创新、试验和部署业务的能力。快速推出业务、快速获取反馈、快速迭代、快速试错。 [*]稳:快速、频繁地特性发布,同时保证业务和系统的稳定性、可用性和持久性。 下面我们稍微解释一下持续集成(CI,Continuous Integration),持续交付(CD,Continuous Delivery),持续部署(CD,Continuous Deployment)的概念,可以去参考:持续集成是什么? [*]持续集成(CI,Continuous Integration):持续集成指的是,频繁地(一天多次)将代码集成到主干。持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。 [*]持续交付(CD,Continuous Delivery):持续交付指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。 [*]持续部署(CD,Continuous Deployment):持续部署是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。 在本文的场景中,主要讲述的是基于华为云的持续部署(CD,Continuous Deployment)。2. 一个华为云上的持续部署方案前期在支撑某客户在华为云上的概念验证(PoC,Proof of Concept)中,有一个很重要的测试场景:自动化CI/CD。具体场景是:客户在私有云中完成持续集成(CI),CI采用自建的工具链;生成结果自动在华为云上完成持续部署(CD),部署在Docker容器中。客户采用Helm charts脚本部署容器应用,因此在客户的CCE(Cloud Container Engine)容器集群所在的VPC中,我们部署了一台服务器安装了Helm client,通过Helm client连接CCE集群的Kubernetes Master完成Docker容器应用部署。客户部署的容器应用中,其中有一个很重要的容器应用是一个job类应用,它的主要工作是:使用一些自动化部署工具完成应用所需资源的创建,应用环境的初始化等等。完成之后即停止。我们采用了:FunctionStage(Serverless)+(Monocular+)Helm Chart + CCE(Kubernetes+Docker)的方案完成持续部署。演示效果良好。具体如下图所示:14221描述如下: [*]客户在私有云中完成持续集成(CI),CI采用自建的工具链。CI的结果是: [*]应用容器镜像上传到华为云容器镜像仓库(SWR, SoftWare Repository for Container) [*]应用部署脚本(例如Helm Chart.yaml, values.yaml)等以约定的打包方式,上传到华为云对象存储服务(OBS, Object Storage Service)的指定桶(Bucket)的相应目录下 [*]因为华为云的FunctionStage(Serverless)和OBS有集成,事先在FunctionStage中配置触发器(Trigger),当指定桶(Bucket)的相应应用目录下有文件更新时(PUT/POST操作,即用户上传了应用部署脚本),自动触发一个Python程序的执行。 [*]这个Python程序会ssh到Helm client,执行一个自动化部署的脚本。此自动化部署脚本会执行资源清理、helm install等动作完成容器应用的部署。 [*]部署的容器应用中,其中有一个很重要的容器应用是一个job类应用,它的主要工作是:使用一些自动化部署工具完成应用所需资源的创建,应用环境的初始化等等。完成之后即停止。 [*]最后的结果是:应用通过helm client部署在CCE容器集群中,该创建的资源(例如RDS-MySQL)成功创建并初始化,资源和应用运行正常。 [*]当然,我们也安装了一个Monocular(Monocular is a web-based UI for managing Kubernetes applications packaged as Helm Charts),允许用户手动部署Helm Charts打包的Kubernetes应用。 3. 部署截图一些部署的截图如下。请注意:这个截图是我手动部署的截图,跟自动化部署的截图是类似的,但更能说明部署过程。 [*]通过Helm client部署容器应用到CCE集群 14158 执行kubectl get pods可以看到应用pod(容器)处于Running状态。 [*]部署过程中通过自动化部署工具创建和初始化的华为云RDS-MySQL资源 14159
  • [干货分享] 实现动画的几种方法
    本帖最后由 小UU 于 2018-4-17 09:14 编辑实现动画的几种方法 动画是通过把某一动态过程分解后,画成许多动作瞬间的画幅,再用摄影机连续拍摄成一系列画面,给视觉造成连续变化的图画。它的基本原理与电影、电视一样,都是视觉暂留原理。医学证明人类具有“视觉暂留”的特性,人的眼睛看到一幅画或一个物体后,在0.34秒内不会消失。利用这一原理,在一幅画还没有消失前播放下一幅画,就会给人造成一种流畅的视觉变化效果。相信很多人都看过动画片,或者手翻书,其实它们与电视、电影的原理都是一样的。 动画如何实现1. Javascript 直接实现动画2. css3动画中的transition 和 animation;3. Canvas动画;4. SVG(可伸缩矢量图形); 14026 1. Javascript 直接实现动画Javascript直接实现动画,主要是通过setInterval或setTimeout方法的回调函数来持续调用改变某个元素的CSS样式以达到元素样式变化的效果,或者使用requestAnimationFrame;14027上面示例的效果是一个灰色的小方块,慢慢的从左边,移动到屏幕右边的动画,每隔16ms就把方块的左外边距增加1px。尽管过程看起来很连贯,但是这种方法依然存在一些问题。因为JavaScript是单线程的,setTimeout是异步操作,加入任务队列后,当js引擎线程中同步代码执行完才会从任务队列中取出执行,可能发生阻塞。另外setTimeOut会导致页面频繁性重排重绘,消耗性能,一般应该在桌面端浏览器,而且不同浏览器对setTimeOut的解析也是不同的,导致同一动画在不同浏览器下效果不一致,在移动端上使用会有明显的卡顿。requestAnimationFrame实现动画的优点是可以避免不必要的过度重绘,但是整体性能和可调节性都不如css3动画。2.css3实现动画TransitionTransition可以实现过渡动画的效果,但是transition并不能实现独立的动画,只能在某个标签元素样式或状态改变时进行平滑的动画效果过渡,而不是马上改变。 transition抓住了所设置变化属性的起始态和完成态,通过设定的速度曲线来完成动画,不支持自定义中间的状态。可以设置发生变化的css属性,默认为all,则所有变化的属性都会在触发时,以动画的形式展现出来。如果把transition和transform配合使用,对元素进行平移、倾斜、缩放,使动画更加丰富生动。transition语法如下:transition: property duration timing-function delay;具体属性值介绍如下: 值描述transition-property规定设置过渡效果的 CSS 属性的名称。(none / all / property)transition-duration规定完成过渡效果需要多少秒或毫秒。transition-timing-function规定速度效果的速度曲线。(linear、ease、ease-in、ease-out、ease-in-out、cubic-bezier(n,n,n,n))transition-delay定义过渡效果延迟时间。示例:14028AnimationAnimation 算是真正意义上的CSS3动画。使用animation属性制作动画可以更加灵活的设置动画,通过对关键帧及其状态以及循环次数的控制,页面元素会在对应的时间按照设定好的样式改变进行平滑过渡。不过区别于Transition,Animation作用于元素本身而不是样式属性,不局限于只有初始状态和结束状态,可以实现更自由的动画效果。animation语法如下:animation: name duration timing-function delay iteration-count direction;具体属性值介绍如下:值描述animation-name规定需要绑定到选择器的 keyframe 名称。(keyframename、none)animation-duration规定完成动画所花费的时间,以秒或毫秒计。animation-timing-function规定动画的速度曲线。(linear、ease、ease-in、ease-out、ease-in-out、cubic-bezier(n,n,n,n))animation-delay规定在动画开始之前的延迟。animation-iteration-count规定动画应该播放的次数。animation-direction规定是否应该轮流反向播放动画。 (normal、alternate)关键帧定义:14029 感兴趣的小伙伴请戳这里:http://www.cnblogs.com/yingzi1028/p/7768595.html使用CSS3 transition和 animation实现动画,它最大的优势是摆脱了js的控制,并且能利用硬件加速以及实现复杂动画效果,但是会存在浏览器兼容性问题。3.canvas动画canvas作为H5新增元素,是页面图形绘制的容器,借助Web API来实现动画的。通过getContext()获取元素的绘制对象,通过clearRect不断清空画布并在新的位置上使用fillStyle绘制新矩形内容实现页面动画效果。它的主要优势是可以应对页面中多个动画元素渲染较慢的情况,完全通过javascript来渲染控制动画的执行,可用于实现较复杂动画。同样都是使用编码的方式由前端开发工程师完成动画效果,canvas要比原生js效率高的多,流畅的多能够轻松的实现更多的动画效果。它的缺点是没有提供为其内部元素添加事件**的方法,需要自己动手实现,使其内部元素能够响应事件。首先获得鼠标在 canvas 上的坐标,计算当前坐标在哪些元素内部,然后对元素进行相应的操作。配合自定义事件,我们就可以实现为 canvas 内的元素添加事件的效果。4.SVG动画SVG用来定义用于网络的基于矢量的图形,其使用 XML 格式定义图像,由SVG元素内部的元素属性控制。Svg不依赖分辨率,基于矢量图,支持事件处理,最适合带有大型渲染区域的应用程序。SVG的一大优势是含有较为丰富的动画功能,原生绘制各种图形、滤镜和动画,并且能被js调用。但是,另一方面元素较多且复杂的动画使用svg渲染会比较慢,CSS3动画的出现让svg的应用变得相对少了。感兴趣的小伙伴请戳这里:https://segmentfault.com/a/1190000008215226
  • [介绍/入门] 使用ServiceComb Go-chassis构建微服务
    本帖最后由 大脸猫爱吃鱼 于 2018-4-12 20:37 编辑作者 王齐林 发布于 2018年1月25日 转自InfoQ 近日,ServiceComb开源了该项目旗下的Go语言微服务框架ServiceComb Go-chassis(以下简称Go-chassis)。作为ServiceComb生态中的重要一环,Go-chassis将和已经开源的Apache ServiceComb(incubating) Java-chassis一道,为用户带来良好的框架级多语言微服务编程体验。同时,ServiceComb Go-chassis未来也会和ServiceComb Java-chassis一样,捐献到Apache基金会中。什么是chassis?Chassis,直译成中文是底盘的意思,它是一种微服务模式,由微服务大师Chris Richardson提出。在这种模式中,用户并不需要自己去处理构建微服务过程中外部配置、日志、健康检查、分布式追踪等那些横切关注点(crosscutting concern),而是将他们交给专门的框架来处理。用户可以更聚焦业务逻辑本身,简单、快速的开发微服务。Apache ServiceComb Go-chassis简介Go-chassis是一个用Go语言编写的微服务快速开发框架,采用插件化设计,将各种功能模块定义为接口,实现功能“可插拔”的同时也带来了非常好的扩展性;用户可以定制开发自己的通讯协议、处理链,对接自己的配置中心、服务发现中心等。Go-chassis的模块及工作流程如上图所示,不同协议请求进入到各协议Server,Server将具体的协议请求转换为Invocation统一抽象模型,并传入Handler chain( 框架内默认内置了大部分微服务治理所需的handler),最终再进入Transport handler,使用具体的协议客户端传输到目标。目前,Go-chassis支持的特性包括但不限于: [*]服务发现(配合ServiceComb现有的ServiceCenter) [*]动态配置管理: [*]负载均衡 [*]流量控制(服务端与客户端) [*]熔断容错 [*]分布式追踪 [*]Metrics [*]日志 [*]路由策略 在通讯协议方面,Go-chassis原生支持REST/Http 和 Highway协议,其中Highway是ServiceComb开发的、基于RPC的高性能通讯协议。使用Go-chassis开发体质指数应用(BMI)下面,我们将以简单的体质指数应用(BMI)为例,说明如何用Go-chassis快速开发微服务。BMI是国际上常用的衡量**胖瘦程度的一个标准,我们开发的BMI应用主要包含两个微服务: [*]体质指数计算器(calculator):负责处理运算事务。 [*]体质指数界面(web-app):提供用户界面及网关服务。 两个微服务之间的关系如下图所示,它们之间通过REST方式进行通信。准备工作在开始开发之前,请确保开发环境上已经完成以下配置 [*]安装 git [*]安装 Go 1.8+ [*]安装 docker [*]下载 ServiceComb go-chassis [code]go get https://github.com/ServiceComb/go-chassis[/code] [*]运行 Service Center 在 ServiceComb 微服务框架中,Service Center 提供服务注册及服务发现功能,可直接使用 docker 运行。[code]docker pull servicecomb/service-center docker run -d -p 30100:30100 servicecomb/service-center:latest[/code]体质指数计算器(calculator) 开发体质指数计算器(calculator)提供运算服务,分为具体业务逻辑、服务注册与配置,启动框架三部分: [*]具体业务逻辑 定义服务结构体[code]type CalculateBmi struct { }[/code]编写计算体质指数(BMI)函数,该函数根据公式13847进行实现:[code]func (c *CalculateBmi) BMIIndex(height, weight float64) (float64, error) { if height = 0 || weight = 0 { return 0, fmt.Errorf("Arugments must be above 0") } heightInMeter := height / 100 bmi := weight / (heightInMeter * heightInMeter) return bmi, nil }[/code]​编写handler函数,其中restful.Context必须作为入参传入。restful.Context中包含了对http调用的Request和Response的常用操作,Read开头的为对Request的读取,包括ReadEntity、ReadHeader、ReadPathParameter、ReadBodyParameter、ReadRequest等;而Writer开头的为对Response的写入操作,包括WriteHeader、WriteJson、WriteError等。[code]import ( rf "github.com/ServiceComb/go-chassis/server/restful" ) …… func (c *CalculateBmi) Calculate(b *rf.Context) { …… //定义返回结构体,此处省略 heightStr := b.ReadQueryParameter("height") weightStr := b.ReadQueryParameter("weight") var height, weight, bmi float64 var err error …… //字符串与浮点数类型转换,此处省略 if bmi, err = c.BMIIndex(height, weight); err != nil { errorResponse.Error = err.Error() b.WriteHeaderAndJson(http.StatusBadRequest, errorResponse, "application/json") return } result.Result = bmi result.CallTime = time.Now().String() b.WriteJson(result, "application/json") }[/code]指定对应的URL路由[code]func (c *CalculateBmi) URLPatterns() []rf.Route { return []rf.Route{ {http.MethodGet, "/calculator/bmi", "Calculate"}, } }[/code] [*]服务注册与配置 完成业务逻辑代码的编写之后,需要将业务逻辑注册到Go-chassis框架,注册时可以同时指定微服务的名称、ID等属性。[code]chassis.RegisterSchema("rest",&CalculateBmi{})[/code]除了在代码中指定的部分属性外,更多的属性是通过配置文件来进行配置。配置文件包括chassis.yaml和microservice.yaml,放置于代码目录下的conf文件夹内。其中,chassis.yaml中配置的是微服务的公共属性,如公共的AppId信息,使用的注册中心类型信息、地址信息,服务的协议、监听地址、注册发现地址、传输协议信息等;microservice.yaml配置的是微服务的私有属性,包括服务名、版本等。chassis.yaml[code]APPLICATION_ID: bmi #应用ID cse: service: registry: address: http://127.0.0.1:30100 #注册中心(ServiceCenter)的地址 protocols: rest: listenAddress: 0.0.0.0:8080 #微服务的监听地址[/code]microservice.yaml[code]service_description: name: calculator #微服务名称 version: 0.0.1 #微服务版本号[/code]启动框架和服务[code]import ( "github.com/ServiceComb/go-chassis" "github.com/ServiceComb/go-chassis/core/lager" ) …… if err := chassis.Init(); err != nil { //初始化框架 lager.Logger.Error("init failed", err) return } chassis.Run() //运行微服务[/code]体质指数界面(web-app)开发开发完后端的calculator服务之后,需要开发提供给用户的交互界面,主要分为前端静态界面、请求转发、服务启动入口三个部分。 [*]前端静态界面 前端静态界面使用了Bootstrap开发,并通过golang 官方库中http.ServeFile将前端静态页面展示出来。[code]func BmiPageHandler(w http.ResponseWriter, r *http.Request) { http.ServeFile(w,r,"external/index.html") }[/code]请求转发体质指数界面(web-app)微服务收到前端界面发过来的请求时,通过core.NewRestInvoker()将请求转发到calculator服务。在转发调用的过程中,用户并不需要感知calculator服务具体的地址和端口,服务发现的过程由go-chassis框架自动完成。[code]func BmiRequestHandler(w http.ResponseWriter, r *http.Request) { queries := r.URL.Query() heightStr := queries.Get("height") weightStr := queries.Get("weight") requestURI := fmt.Sprintf("cse://calculator/bmi?height=%s&weight=%s", heightStr, weightStr) restInvoker := core.NewRestInvoker() req, _ := rest.NewRequest("GET", requestURI) resp, _ := restInvoker.ContextDo(context.TODO(), req) w.Header().Set("content-type", "application/json") w.WriteHeader(resp.GetStatusCode()) w.Write(resp.ReadBody()) }[/code] [*]服务配置与启动 体质指数界面(web-app)服务的配置文件同样包括chassis.yaml和microservice.yaml两个yaml文件,具体内容如下:chassis.yaml[code]APPLICATION_ID: bmi #应用ID cse: service: registry: address: http://127.0.0.1:30100 #注册中心(ServiceCenter)的地址[/code]microservice.yaml[code]service_description: name: web-app #微服务名称 version: 0.0.1 #微服务版本号[/code]与calculator服务不同,体质指数界面(web-app)在Go-chassis框架内是一个消费者类型的服务,故只需调用chassis.Init()对Go-chassis框架进行初始化。[code]func main() { http.HandleFunc("/", BmiPageHandler) http.HandleFunc("/calculator/bmi", BmiRequestHandler) if err := chassis.Init(); err != nil { lager.Logger.Error("Init fail", err) return } port := flag.String("port", "8889", "Port web-app will listen") address := flag.String("address", "0.0.0.0", "Address web-app will listen") fullAddress := fmt.Sprintf("%s:%s", *address, *port) http.ListenAndServe(fullAddress, nil) }[/code]界面效果通过上述步骤,体质指数(BMI)应用已经开发完毕,可以通过http://localhost:8889访问该应用,届时将能看到如下界面,并可输入身高和体重信息验证服务是否正常运行。使用Go-chassis进行微服务治理除了基础的业务逻辑开发外,Go-chassis提供了丰富的微服务治理功能。下面将在刚刚开发的体质指数应用(BMI)基础上,介绍如何使用Go-chassis进行微服务治理。负载均衡当对体质指数计算器(calculator)进行水平扩展时,需要将请求均衡地分发到多个体质指数计算器(calculator)上。Go-chassis的负载均衡功能包括负载均衡策略和负载均衡过滤器两种方式。微服务实例在经过过滤器中制定的规则初筛之后,根据策略算法选出一个合适的实例进行下一步处理。Go-chassis内置了RoundRobin,Random,SessionStickiness,WeightedResponse四种策略,其中默认使用的策略为RoundRobin。此外,无论是负载均衡策略还是负载均衡过滤器,开发者都可以根据自己的需求进行定制。 [*]开启 负载均衡功能默认开启,不需要另外配置。若用户希望使用RoundRobin之外的策略,可以在配置文件chassis.yaml中进行指定。[code]cse: loadbalance: # 全局负载均衡配置 strategy: name: Random microserviceA: # 微服务级别的负载均衡配置 strategy: name: SessionStickiness[/code]对体质指数计算器(calculator)进行水平拓展时,用户只需复制原有代码,并在配置文件中修改监听端口,使得新的实例在另一个端口运行即可。 [*]微服务实例的本地缓存 为了便于区分不同的运行实例,在体质指数计算器(calculator)的实现中新增了返回实例ID的代码。[code]import ( "github.com/ServiceComb/go-chassis/core/registry" ) …… items := registry.SelfInstancesCache.Items() for microServiceID, _ := range items { instanceID, exist := registry.SelfInstancesCache.Get(microServiceID) if exist { result.InstanceId = instanceID.([]string)[0] } }[/code]Go-chassis框架初始化时,会将注册中心中的实例缓存到本地,并每30秒同步一次注册中心和本地缓存的数据(可配置)。代码中使用了本地缓存的数据来获取实例ID。 [*]验证 上述操作完成后,在界面上点击Submit 按钮,可以发现实例ID交替变换。流量控制 [*]开启 流量控制机制通过控制数据传输速率来避免微服务过载运行。用户可以进行服务端流量控制,限制接收处理请求的频率,在体质指数计算器(calulator)的chassis.yaml中可进行服务端流量控制的配置:[code]cse: handler: chain: Provider: default: ratelimiter-provider #添加服务段流量控制的handler flowcontrol: Provider: qps: enabled: true # 是否启用流量控制 limit: web-app: 1 # key为指定要限制的微服务调用者名称,此处web-app为调用calculator的微服务的名称;value为每秒允许的请求数。[/code]也可以进行消费端流量控制,限制发往指定微服务的请求的频率。在体质指数界面(web-app)中的chassis.yaml中配置:[code]cse: handler: chain: Consumer: default: ratelimiter-consumer #添加消费者段流量控制的handler flowcontrol: Consumer qps: enabled: true # 是否启用流量控制 limit: calculator: 1 # key为指定要限制的请求发往的微服务的名称;value为每秒允许的请求数[/code]验证访问 http://localhost:8889,在身高和体重的输入框中输入正数,尝试在1秒内多次点击 Submit 按钮。此时,能看到所有的请求将被后台延迟处理,处理的频率为1次/秒。熔断与降级 [*]开启 熔断与降级主要用于解决或缓解服务雪崩的情况,即个别微服务表现异常时,系统能对其进行处理,从而避免资源的耗尽。用户可以在服务端体质指数计算器(calculator)的chassis.yaml 文件中指明使用服务治理的处理链及指定熔断和容错策略:[code]cse: handler: chain: Provider: default: bizkeeper-provider circuitBreaker: Provider: calculator: requestVolumeThreshold: 3 #10s内发生错误的阈值,超出阈值触发熔断 fallback: Provider: enabled: true fallbackpolicy: Provider: policy: returnnull #出错后的处理策略[/code] [*]验证 [*]使服务进入熔断状态。访问 http://localhost:8889,在身高或体重的输入框中输入一个负数,连续点击三次或以上 Submit 按钮,此时在网页下方能看到类似左图的界面。 [*]验证服务处于熔断状态。在身高和体重的输入框中输入正数,再次点击 Submit 按钮,此时看到的界面依然是类似左图的界面。同时在 体质指数计算器(calculator) 后台运行日志中也能看到 circuit open 的日志。 [*]验证服务恢复正常。约5秒后 ,在身高和体重的输入框中输入正数,点击 Submit 按钮,此时界面显示正常。 分布式调用链追踪开启分布式调用链追踪用于有效地监控微服务的网络延时并可视化微服务中的数据流转。启用分布式调用链追踪,需要在体质指数计算器(calculator) 的 chassis.yaml 文件中添加如下配置,指定追踪数据上报的开关以及上报地址、上报类型等。[code]cse: handler: chain: Provider: default: tracing-provider tracing: enabled: true collectorType: zipkin collectorTarget: http://localhost:9411/api/v1/spans[/code]同样的,在体质指数界面(web-app)中的chassis.yaml中进行如下配置:[code]cse: handler: chain: Provider: default: tracing-consumer tracing: enabled: true collectorType: zipkin collectorTarget: http://localhost:9411/api/v1/spans[/code]此外,还需要运行Zipkin 分布式追踪服务,可以采取Docker方式:[code]docker pull openzipkin/zipkin docker run -d -p 9411:9411 openzipkin/zipkin[/code]验证首先访问 http://localhost:8889 ,在身高和体重栏处输入正数,并点击 Submit 按钮。然后访问 http://localhost:9411 ,进入Zipkin查看分布式调用追踪情况,可得下方界面。​Metrics [*]开启 监控数据能直观的显示微服务应用的性能数据,帮助更好的进行微服务治理、制定弹性伸缩策略等。Go-chassis支持输出Prometheus格式的监控数据,提供的数据包括Golang运行时的数据、微服务进程的内存占用、CPU占用情况等。要使用监控功能,需要在体质指数计算器(calculator) 的chassis.yaml 文件中添加下列内容:[code]cse: metrics: apiPath: /metrics enable: true enableGoRuntimeMetrics: true #是否开启go runtime检测 [/code] [*]​​​​验证 首先访问 http://localhost:8889 ,在身高和体重栏处输入正数,并点击 Submit 按钮。然后访问 http://localhost:8080/metrics(其中8080为体质指数计算器(calculator)服务端监听的端口),可以得到下图所示的监控数据:加入ServiceComb社区​ 本文介绍了ServiceComb Go-chassis的基本特性以及如何使用ServiceComb Go-chassis开发体质指数应用(BMI)以及进行微服务治理。整个示例的源代码可以从Github上获取。同时,作为一个新开源的项目,ServiceComb Go-chassis诚挚的欢迎大家一起参与社区讨论,贡献代码,共同努力打造“最好用的Go语言微服务框架”。 [*]ServiceComb Go-chassis github地址:https://github.com/ServiceComb/go-chassis [*]ServiceComb官方网站:http://servicecomb.incubator.apache.org/ [*]ServiceComb邮件列表:[email]dev-subscribe@servicecomb.incubator.apache.org[/email]
  • [介绍/入门] 商用级Service Mesh服务的设计之道
    作者介绍:田晓亮,8年软件行业经验,曾就职于三星,2012年进入云计算领域,对PaaS,DevOps,APM有深入的研究和实践经验,方案支撑近千台VM中的应用部署监控。 2016年加入华为担任架构师,负责微服务的Go语言开发框架及Service Mesh设计和落地,Go语言微服务框架已被华为5G核心网络采用,Service Mesh服务也已在华为云商用上线。 微服务架构是个难题,但解法有多个微服务是一个很大的概念,从团队组织到最佳实践似乎都有实施微服务的一些指导。我们这里只提构建微服务的架构模式,也就是关乎到你用什么样的方式来构建你以微服务架构来组织的应用系统。近些年随着微服务的火热,越来越多的团队开始进行实践,将微服务纷纷落地,也许你是从0开始,一步步地完成了单体应用向微服务的改造,让我们来看看,你解决了多少问题。 13830图1 微服务架构需要解决的问题 微服务将原本内存中函数的调用转换为网络中的调用后,就牵扯到这些问题,而任何一个分支展开,都会涉及一系列的问题。业务开发者也许真的有精力去学习架构相关的复杂问题,然而对于公司来说,真正有价值的是业务本身,让业务开发者解决这些问题需要花费浪费大量的时间精力,导致业务上线受到影响。那我们来看看是否有便捷的方式来解决业务开发者的痛点。Chassis模式 一句话来概括:一种语言开发框架来作为微服务开发的底座,封装掉复杂性,帮助你解决跨网络带来的问题,让用户聚焦在上层业务逻辑的开发。通常情况下会实现以下功能: [*]日志、Metrics、分布式追踪数据上报 [*]健康检查 [*]对接统一的配置中心实现动态配置 [*]对接注册中心 [*]实现负载均衡、熔断降级、容错、限流等保证高可靠运行的功能 现在我们来看看业界有哪些可用的Chassis框架 [*]Spring Cloud [*]ServiceComb [*]Dubbo [*]Go-Micro [*]Go-Kit 先不细去纠结微服务的严格定义,也先暂且搁置诸如“某些老旧框架是否是真的微服务框架”这类争议,从实现方式来看,上述服务化框架都是将分布式系统开发的复杂性进行了一定程度的封装然后提供了简便的开发接口供使用者调用。但是,用这种方式构建微服务还有一些问题: [*]多语言SDK支持:微服务提倡不同组件使用最适合它的语言开发,但是这需要每种语言都有开发框架,不断实现相同的功能。上面可以看到只有go语言和Java语言出现了微服务开发框架,其他语言呢? [*]不论代码侵入程度,都需要开发者思考如何与SDK结合,并从代码层面做出改变,对于大部分开发者来说都是一个高曲线的学习过程。 [*]绑定了特定技术栈,一旦想抽身就需要一定程度上的代码改造。 [*]老旧单体应用由于无人维护,耦合程度高等问题无法进行改造,在进行微服务拆分的过程中重用遗留代码变得无比困难。而且微服务的拆分难以分步进行,需要一个相对较长的周期将系统整体拆分后才能上线。 我们知道技术演进来自于在实践中不断地将功能抽象,解耦,封装,服务化。 [*]云计算技术出现前是数据中心虚拟化,不断地实践使技术发展形成理论和新的实践。IaaS是一种封装,如今开发者与大部分技术团队不需要再学习虚拟化等技术以及如何维护数据中心。 [*]没有TCP/IP的时代,开发人员需要自己考虑网络间数据包的传输,以及网络传输代码与业务代码完全耦合的问题,如今,开发者已经不需要关心,操作系统和开发语言已经封装好网络传输过程。 是否也可以把语言框架提供的能力抽象,成为服务? 在引入后面内容前,我先介绍下SideCar模式SideCar模式 [*]在近些年受到Kubernetes对容器调度方式的启示而日渐受到关注的一种功能部署模式,也是一种微服务的设计模式。 [*]主要利用了一个Pod中的容器可以共享存储与网络的能力,或者说在一个Host中,这个模式也同样适用。 [*]一般分为应用容器和工具容器,工具容器可以重用。 一个典型的场景如下: 13831图2 SideCar典型场景 应用容器与日志同步工具在同一个Pod下,共享存储卷,应用程序生成的日志文件会由日志同步工具收集并发送到类似kafka,elasticsearch这样服务中。在这样的架构下我们获得了什么呢? [*]以容器作为基础打包单元,那么就可以分给不同的团队进行开发测试 [*]Sidecar容器可重用,可以与不同的容器结合 [*]以容器作为错误边界,使服务能够独立开发和测试,比如应用服务在没有日志保存功能的情况下也可以独立运行 [*]独立回滚与更新(但需要考虑复杂的版本组合,建议使用语义版本管理对版本进行控制) 在这个模式的基础之下,我们引入了Service mesh。Service Mesh 新瓶中的那一杯老酒什么是Service Mesh Service mesh最早是由Linkerd给出的定义,我们来看看英文版:[indent]A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware. (But there are variations to this idea, as we’ll see.)The concept of the service mesh as a separate layer is tied to the rise of the cloud native application. In the cloud native model, a single application might consist of hundreds of services; each service might have thousands of instances; and each of those instances might be in a constantly-changing state as they are dynamically scheduled by an orchestrator like Kubernetes. Not only is service communication in this world incredibly complex, it’s a pervasive and fundamental part of runtime behavior. Managing it is vital to ensuring end-to-end performance and reliability.[/indent]大致的意思如下: [*]一种基础设施层服务,服务间的通信通过service mesh进行 [*]可靠地传输复杂拓扑中服务的请求,将它们变成现代的云原生服务 [*]一种网络代理的实现,通常与业务服务部署在一起,业务服务不感知 [*]一种网络模型,在TCP/IP之上的抽象层,TCP/IP负责将字节码可靠地在网络节点间传递,Service mesh则复杂将服务间的协议请求可靠地在服务间进行传输。它们不关心传输的内容 [*]TCP/IP仅仅负责传输,但Service mesh可对运行时进行控制,使服务变得可监控,可管理。 为什么使用Service Mesh [*]无需考虑每种语言都要解决的问题 [*]对业务代码0侵入,开发者无需关心分布式架构带来的复杂性以及引入的技术问题 [*]对于不适合改造的老旧单体应用,提供了一种接入分布式环境的方式 [*]微服务化的进程通常不是一蹴而就的,很多应用选择了演进的方式,就是将单体应用一部分一部分地进行拆分。而在这个过程中,使用Service Mesh就可以很好地保证未拆分的应用与已经拆分出来的微服务之间的互通和统一治理 [*]开发出的应用既是云原生的又具有云独立性,不将业务代码与任何框架,平台或者服务绑定 依然没有银弹,我们来看看Service mesh解决不了的问题 [*]无分布式事务方案 [*]Service Mesh组件代理请求转发,会在一定程度上降低系统通信性能 [*]没有Event Driven的框架 [*]侵入式框架以源码和业务代码结合,有较强定制和扩展能力,Service mesh相对不易定制扩展 [*]在运行时,依赖单独的Service Mesh代理,多了一个故障点。整个系统的运行和运维也强依赖于Service Mesh组件的能力 Service Mesh的实践历程和设计思路Service Mesh在华为公司内部的发展历程 第一代: 基于NGINX的微服务代理该平台是华为公司内部使用的微服务开发部署运行平台,开发于2013年,用于公司内部某电信业务。在这个业务系统中有大概400多个左右的微服务,实例数量根据局点大小不一样,一个典型的部署为800多个左右实例的规模。整体架构如下:13832图3基于NGINX的微服务代理的平台整体架构 其中的Internal Router组件用来给开发者解决分布式架构中的可靠传输问题: [*]使用高性能nginx及其相应的lua扩展作为Internal Router,将Http服务接入 [*]使用RouteAgent负责注册/注销实例,更新IR的实例信息 [*]使用zookeeper作为注册中心 [*]以Per-Host的方式部署在微服务所运行的环境中 用这种方式构建的微服务环境已经在超过200个局点的生产环境下得到使用,整体运行情况良好。但是随着时间的推移,当业务对敏捷的要求越来越大,而且容器的使用也越来越广泛,这种方式带来了一些问题: [*]使用lua脚本扩展注册发现,负载均衡,熔断,降级,容错,限流,但lua的扩展性有一定的局限 [*]用RouteAgent负责服务的注册以及每个NGINX上服务实例路由的刷新,RA需清楚地感知本节点上的微服务都有哪些,但是使用Kubernetes做容器调度后微服务和实例的分布信息在K8S里面集中记录 [*]容器的IP更多,变化更频繁,使用RouteAgent刷新NGINX路由的方式会导致NGINX服务受到影响,频繁的路由刷新导致业务运行收到影响 [*]当IR服务失败后,整个Host中的服务都会丢失,无法与外界建立联系 为了解决这些问题,出现了第二代的解决方案: HSA Sidecar13833图4 HSA Sidecar设计 HSA是华为内部的一套微服务开发框架,它提供了注册中心,配置中心,java开发框架,以及SideCar等组件 [*]基于Java 微服务框架开发,非侵入式通信方式,支持RPC与Http,提供SOAP协议转换,但会导致性能下降 [*]与微服务部署在一个Pod中即Sidecar模式 [*]作为代理服务,使微服务自动获得注册发现,负载均衡,熔断,降级,容错限流等功能 [*]占用资源很高,一个应用实例一个Sidecar实例的部署方式,会占用过高资源 虽然第一代的问题解决了,但是第二代的Sidecar在性能和资源占用上有很大的问题,在少量的技术项目中试用后,因为资源占用过高的问题无法在大规模环境中推广使用。CSE Mesher介绍 Service Mesh 模式的一种实现。基于自研的Go语言微服务框架(该框架即将开源)开发,使用ServiceComb注册中心(已经开源)与CSE配置中心,以Sidecar的方式部署在微服务所运行的环境中,也可以PerHost模式运行。在用户数据面使用,提供VM部署、公有云部署、容器部署,占用资源小(闲置10多M,并发运行时30多M)。基本能力 注册发现注册中心为插件化模块,目前对接了ServiceComb、Service Center,未来还会有更多的系统对接进来 13834图5 可插件化的注册中心 路由规则管理根据预定义的路由规则对请求进行引流 [*]支持权重引流:比如将5%的流量引到购物车的1.0版本,20%引到2.0版本 [*]可根据服务请求特征进行引流:比如消费者的请求中Header带有的用户名为Json,那么可以引流到某个服务的特定版本中 [*]利用读写锁,路由可在运行时更新,并且不丢失请求 协议转换与不同框架的对接与统一治理使用标准OpenAPI契约,可以实现Dubbo RPC协议与Http协议的互转,用于透明地接入遗留的Dubbo应用并对遗留应用进行统一的服务治理使用负载均衡与重试策略 [*]负载均衡器会调用注册中心插件进行实例查询 [*]在查询中的实例里表中,使用Filter进行过滤 [*]将过滤后的实例传入Strategy中进行实例选择 [*]默认提供RoundRobin Random,会话粘滞策略 [*]具备容错能力且加入Backoff算法,增强网络稳定性 使用熔断降级熔断使用的断路器对一个执行过程进行包装,断路器负责监控维护每个执行过程的状态、结果、错误、超时。当达到一定阀值时就会熔断,并触发降级。以这样的机制来保护服务提供者,不会出现级联的雪崩式错误。使用限流提供了消费者端与提供者端限流用户可以通过配置来限制每秒只允许多少个请求被发出或者接受对接监控Metrics:提供了主动上报到CSE Dashborad的方式。也可与华为公有云APM,Prometeus对接 分布式追踪:对接Zipkin架构设计 整体架构13835图6 CSE Mesher整体架构 Mesher背靠CSE组件,使用微服务引擎中的服务中心与配置中心等服务作为控制面,Mesher与业务代码部署在一起运行在数据面数据面13836图7 CSE Mesher数据面 即Service mesh组件本身,对所有请求进行处理,它有以下功能 [*]发现服务 [*]执行路由策略 [*]负载均衡 [*]拦截所有请求并处理,转发 [*]认证鉴权 [*]生成监控数据 控制面13837图8 CSE Mesher控制面 为管理人员提供统一的管理入口,为所有运行的mesher提供配置下发但不会介入服务请求 [*]注册中心:服务上下线感知 [*]下发配置:使用Web Console对运行时更改,负载均衡,熔断容错,限流等策略 [*]对接监控服务与监控页面 [*]调度引擎:这里并非是微服务引擎提供的组件,是可选组件,这个组件负责拉起服务,维护实例数,在资源池中调度分配实例,这里推荐使用ServiceStage负责实例的生命周期管理 运行场景 不同的部署方式与业务服务部署在一起有3种运行模式1.仅消费者使用Mesher,提供者为使用ServiceComb开发框架的服务或者裸服务,下图为例:ServiceC为裸服务,它既不用mesher也不用SDK,那么起码它需要自己注册到服务中心中,供其它服务发现,否则无法进行访问。13838图9 仅消费者使用Mesher 2.消费者与提供者均使用Mesher13839图10 消费者与提供者均使用Mesher 以这种方式运行的服务可以使用透明TLS传输,并且拥有了服务端限流3.提供者使用Mesher,消费者A使用ServiceComb SDK进行开发可直接发现服务B,但是消费者C作为裸服务需要自己发现服务B 13840图11 仅提供者使用Mesher 运行时请求处理消费者端请求 13841图12 消费端发送请求流程 上图为例:SockShop服务将mesher作为代理并使用地址http://order/list访问订单服务 [*]Destination Resolver 目标微服务名解析,支持插件定制,可根据请求特征决定微服务名是什么 [*]Source Resolver 将IP地址解析为微服务实体信息 [*]路由决策 根据Source和Destination 信息决定最终要访问哪个微服务 [*]处理链 处理链为可随时**或减少的模块,在这里Mesher实现了限流,熔断,降级,负载均衡等功能 [*]传输层 最终请求通过传输层发送到目标微服务实例 提供者端接收请求 13842图13 提供者端接收请求流程 上图为收到远程请求后的处理过程 [*]服务端接到请求,将IP地址解析为微服务信息 [*]进入处理链,这一步并没有负载均衡而是直接使用local selection 进行处理 性能对比 13843图14 Mesher1.0、Istio 0.1.6 (Envoy)、Linkerd1.1.3性能对比 在性能对比后,我聊下自己的看法 [*]Linkerd 作为java实现的service mesh,受到资源占用的拖累,考虑到数据中心成本,不适合作为SideCar和应用部署在一起,相信它的主要场景在于Kubernetes Ingress和Daemonset,并且由于只有数据面,需要和别的生态系统对接获得控制面能力,否则,业务团队又要考虑自己开发控制面。 [*]目前Istio已知问题是每次请求都要调用一次Mixer API来传送metric数据,相信未来版本能够解决,但不能满足我们内部的产品节奏。 [*]作为对比,Mesher通过Channel与Go协程机制主动上报metric数据,以此获得更高的性能,机制如下:模块将数据传送到channel中,协程收到信号并主动上报,在这样的机制下开启监控,性能只有百分之2左右的下降。 13844图15 Metric数据上报机制 一些思考以及未来华为为什么开发了自己的Service Mesh [*]Istio的性能问题没有解决,Envoy每次访问请求Mixer API导致性能下降 [*]Istio强绑定Kubernetes平台(1.7.4+),虽然有着良好的架构,对接不同平台不是问题但需要时间,Mesher贯彻不将开发者绑定到任何框架和平台的理念 [*]从成本角度讲Linkerd并不适合做SideCar部署,JVM资源占用较多 [*]过去在ServiceComb中的积累:Service center,Config center,Go SDK,Governance UX已经提供了大量技术积累,可用于做Mesher的控制面。 [*]既然非侵入式与侵入式都不是银弹,侵入式(ServiceComb Java)与Mesher提供的非侵入式框架的无缝结合,混编就变得有价值了,开发者可以因地制宜,选择适合自己的方案。 Service Mesh是个大舞台 现在已经出现了越来越多的Service mesh实现: [*]数据面:Linkerd,Nginx,Envoy [*]控制面:Istio Linkerd 是在2016年出现的,Envoy在6个月后出现,不过Envoy已经在2015年就商用了。这两个项目也是最有名的Service Mesh。Istio在2017年5月出现,它提供了控制面,并使用Envoy作为数据面的Service Mesh。目前已经开始有些Service Mesh提供者宣布与Istio进行集成,比如Linkerd和Nginx。这意味着控制面与数据面是解耦的,任何的控制面都可以和数据面Service Mesh进行集成。CSE Mesher也会考虑与Istio进行集成,成为除了Envoy之外的另一种数据面选择。实际上在开源项目之外,很多公司内部也早已用类似的方案进行自己系统的构建,各自有各自的特点用来解决自己的实际问题。Istio成为CNCF里面一个被认为是“Kubernetes之后的第二个爆款”是有理由的,它提供了一种从平台的角度解决应用架构的思路,进一步简化了应用的开发。我们也相信在这个大舞台上会有更多的方案出现,而这些方案的出现也会让微服务和Cloud Native应用的构建方式有更多地选择。我们团队也已经基于多年的实践经验将当前的内部Service Mesh方案包含在华为云的“微服务引擎”中,开放给外部用户使用。希望可以作为一种参考,可以给正在选择实施微服务架构方案的读者一些帮助。
  • [热门活动] 【3月干货阅读排行榜】应用服务论坛3月都爱看什么?
    本帖最后由 橘色祥云楼楼主 于 2018-4-9 11:02 编辑排行榜链接1.重磅!华为云国内首发Windows容器服务http://forum.huaweicloud.com/viewthreaduni-6883-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-092.三亿用户量的微服务化改造 华为云是如何做到的?http://forum.huaweicloud.com/viewthreaduni-6971-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-093. 3月15日晚20:00点直播预告:使用Apache SkyWalking APM 监控 Apache ServiceCombhttp://forum.huaweicloud.com/viewthreaduni-7097-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-094.华为云正式开放区块链服务!与车车科技发布实践应用方http://forum.huaweicloud.com/viewthreaduni-7558-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-095.【CPTS新手入门】全5期,快速上手全收录!http://forum.huaweicloud.com/viewthreaduni-6829-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-096.华为云的Kubernetes实践之路http://forum.huaweicloud.com/viewthreaduni-7719-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-097.【1V1专家咨询】你来提问题,产品经理来回答!http://forum.huaweicloud.com/viewthreaduni-7146-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-098.携手开源中国,华为云容器镜像服务SWR助力用户打造DevOps流程http://forum.huaweicloud.com/viewthreaduni-6990-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-099.【你问专家答】与技术大咖的亲密交流之旅---#云容器实例#http://forum.huaweicloud.com/viewthreaduni-7211-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0910.华为云应用服务大型互动专场,邀您体验趣玩黑科技!http://forum.huaweicloud.com/viewthreaduni-7265-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0911.Cloud 2.0时代,华为云推出四大云上应用服务http://forum.huaweicloud.com/viewthreaduni-7643-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0912.AOS的基本概念!http://forum.huaweicloud.com/viewthreaduni-7514-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0913.【2月干货阅读排行榜】应用服务论坛2月都爱看什么?http://forum.huaweicloud.com/viewthreaduni-6960-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0914.ServiceComb不能做api gateway,但是却有api gateway的一些功能,功能重合怎么办http://forum.huaweicloud.com/viewthreaduni-7171-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0915.【云图说】应用性能管理采集知多少http://forum.huaweicloud.com/viewthreaduni-6888-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0916.管家婆发布基于华为云Windows容器解决方案http://forum.huaweicloud.com/viewthreaduni-7562-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0917.如何在API网关上调用APIhttp://forum.huaweicloud.com/viewthreaduni-6970-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0918.配置中心的 代码会开源吗http://forum.huaweicloud.com/viewthreaduni-6869-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0919.【求助】 配置中心拉取配置时 http返回401 Unauthorizedhttp://forum.huaweicloud.com/viewthreaduni-6859-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-0920.docker save后在界面上传镜像http://forum.huaweicloud.com/viewthreaduni-6918-filter-author-orderby-dateline-page-1-1.html?newsletter2018-04-09
  • [干货分享] 解决回调深渊的利器!这就是Promise!
    Javascript有很多强大的功能,其中一个就是它可以轻松的搞定异步编程。Node.js用回调函数代替了事件,使异步编程在js领域更加流行。但当更多的程序开始使用异步编程时,事件和回调函数确不能满足开发者想要做的所有事情,而Promise就是这些问题的解决方案。 Promise Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。 多么强大的东西都有浏览器兼容性的问题: 优点和缺点 优点:可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。 缺点:首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。 Promise 的生命周期 每一个Promise都会经历一个短暂的生命周期:先是处于进行中pending(Promise对象的初始状态,等到任务的完成或者被拒绝)状态,此时操作未完成,所以它也是未处理的;一旦异步操作执行结束,promise就会进入以下两种状态中的一种:Resolved又称fulfilled(任务执行完成并且成功的状态);Rejected(任务执行完成并且失败的状态)。 Promise的状态只可能从Pending状态转到Resolved状态或者Rejected状态,而且不能逆向转换,同时Resolved状态和Rejected状态也不能相互转换。 Then()方法 所有的Promise都有then()方法,且同一个Promise对象可以注册多个then方法,它接受两个可选参数:第一个是当Promise的状态变为resolved时要调用的函数;第而个是当Promise的状态变为rejected时要调用的函数。注意事项:如果省略这两个参数,或者提供非函数,那么将创建一个没有其他处理程序的新Promise,只是采用 Promise 的最终状态,then() 被调用。 如果省略第一个参数或提供的不是函数,创建的新 Promise 简单地采用 Promise 的完成状态,then()被调用(如果它变为完成)。 如果省略第二个参数或提供的不是函数,创建的新 Promise 简单地采用 Promise 的拒绝状态,then()被调用(如果它被拒绝)。 Then()方法返回的是一个新的promise对象,因此可以采用链式写法; 下面这个例子使用then方法依次指定了两个回调函数,第一个函数执行完,执行第二个回调函数,实现依次打印1,2,3 catch()方法 Promise还有一个catch()方法,相当于只给其传入拒绝处理程序的then()方法。Promise.catch()方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。 上面代码中,promise抛出一个错误,就被catch()方法指定的回调函数捕获。 一般总是建议,Promise 对象后面要跟catch()方法,这样可以处理 Promise 内部发生的错误。Catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。 将其他对象变为Promise对象 promise.resovle()和Promise.reject()方法,可以将不是Promise对象作为参数,返回一个Promise对象。不同的是Promise.resovle()返回的是完成态的Promise,Promise.reject()创建已拒绝的Promise。 Promise.resovle()和Promise.reject()方法都可以接受非Promise的thenable对象作为参数。如果传入一个非Promise的Thenable对象,返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则以该值为成功状态返回promise对象; 有两种情形: 1.假设传入的参数没有一个.then方法,那么这个返回的Promise对象变成了resolve状态,其resolve的值就是这个对象本身。 2.假设传入的参数带有一个then方法(称为thenable对象), 那么将这个对象的类型变为Promise,其then方法变成Promise.prototype.then方法。 响应多个Promise Promise有一个"静态方法"——Promise.all(注意并非是promise.prototype), 这个方法接受一个元素是Promise对象的数组。这个方法也返回一个Promise对象,如果数组中所有的Promise对象都resolve了,那么这些resolve的值将作为一个数组作为Promise.al()l这个方法的返回值的(Promise对象)的resolve值,之后可以被then方法处理。如果数组中任意的Promise被reject,那么该reject的值就是Promise.al()l方法的返回值的reject值。then方法的第一个回调函数接收的resolve值(如上所述,是一个数组)的顺序和Promise.all中参数数组的顺序一致,而不是按时间顺序排序。 还有一个和Promise.all()相类似的方法Promise.race(),它同样接收一个数组,只不过它只接受第一个被resolve的值。 Promise的兴起,解决了在异步方法调用中,会出现回调函数一环扣一环的情况。不仅代码写起来美观,而且问题复杂的时候,阅读代码的人也容易以理解。 [color=rgb(51,51,51)]
  • [行业前沿] 华为云的Kubernetes实践之路
    本帖最后由 橘色祥云楼楼主 于 2018-3-29 11:36 编辑13375 华为与 Kubernetes 的渊源颇深,早在 Kubernetes 刚开源的时候就以社区创始成员及白金会员的身份加入其中。目前拥有 1 个 Steering Committee 席位和 5 个 Maintainer 席位。 华为自身基于 Kubernetes 的实践 加入初期,作为全球最大的电信设备制造商之一,华为内部 IT 运维着遍布全球的八个数据中心,在 100K + VM 中运行 800 多个应用程序,使用虚拟机封装应用程序,但每次启动虚拟机都花费了大量的时间,这给管理及部署基于虚机应用程序的高成本和低效率带来了严峻的挑战。因此华为决定利用 Kubenetes 技术对自身 IT 系统进行容器化改造。 与此同时,华为通过参与和贡献 Kubernetes 项目,为自身带来了在规划、网络、多集群联合、应用支持、安全、可扩展性和政策执行等方面的良好设计、代码和文档管理,以及在服务治理方面的收益。通过自身的容器化改造实践,在受益的同时又将自身遇到的实际问题不断的贡献给社区,与社区成员一同推动 Kubernetes 的发展。 比如,在华为内部 IT 系统的实践历程中,业务的全球化属性给平台带来了混合云、跨地域、多 DC 部署方面的需求,这与社区发展多集群联邦的理念不谋而合。因此,华为在集群联邦项目成立之初就积极参与其中,主导了架构设计以及联邦级别的无状态应用、短任务支持、集群间策略调度、应用跨集群自动伸缩等关键特性开发。目前集群联邦已在社区正式孵化为独立子项目。 另一个例子是早期的 K8S 并不支持亲和反亲和等高级调度策略,使得大型传统应用改造上云十分困难。在华为公司对应用做微服务拆分和容器化改造的过程中,最典型的问题就是拆分后的组件间如何高效地通信。在传统方案中,往往有多个组件的业务进程部署在同个虚机上,组件间交互可以通过进程间通信来实现。应用改造后,组件变成了 k8S 中的 Pod,被相对独立地调度和拉起,通过容器网络互相通信。当一个复杂应用的各个组件十分分散时,网络通信的时延会大幅增加。 一方面,针对这个问题,华为在 k8S 社区的主导实现了节点亲和反亲和调度、应用间亲和反亲和调度、Taints tolerations 等高级调度机制。通过给 Pod 配置高级调度策略干预应用组件的分布,配合容器网络在路由策略上的优化,访问时延问题得到了显著的改善。 另一方面,在集群规模和性能方面,华为也做了很多探索与实践。面对大规模场景下海量 Service 的管理性能问题,华为设计实现并向社区贡献了使用 IPVS 管理 service 路由规则的方案,将 k8S 对 service 的管理规模从上千提升到了数万的级别。 华为云应用服务与 Kubernetes 华为云应用服务产品均围绕着“容器”为中心构建,致力于帮助客户容器化的应用在云上高效地开发、交付与运维,并保障应用运行时的高性能、高可靠、高弹性。目前,华为云应用服务产品以基于 K8S 的华为云容器引擎(CCE)为核心,协同补齐了完整的应用开发、交付与运维流程,为客户提供完整的一站式云上应用生命周期管理方案。 华为云应用服务大体上可以分为三大类: 第一类围绕着 Kubernetes 核心功能,也就是容器编排与调度,与下层的基础设施层包括计算、网络、存储,以及水平的权限控制、网络防护、镜像仓库等服务进行整合形成一个容器化基础设施平台,并向上对接到集群管理、多 DC/AZ、多区域管理实现云上的水平弹性。通常大家所提到的“容器服务”或“容器云”大部分都是指这一类服务。华为云所提供的云容器引擎(CCE)、云容器实例(CCI)归属于此类。两者均基于 Kubernetes 构建,但技术路线偏重点有所区分。 CCE 的服务形态是用户专属的 Kubernetes 集群(Kubernetes as a Service),用户能够控制整个 Kubernetes 集群的资源与应用,并且可以调用完整的 Kubernetes API,以及安装各类 Addon 以及自定义扩展比如调度器、工作负载控制器等;而 CCI 的服务形态是无服务器容器(Serverless Container),用户无需感知 Kubernetes 集群,通常只需要调用 Kubernetes Workload API 进行应用的管理即可,而把资源全部交由华为云进行自动调度与管理。因此,通常 CCE 适合业务半托管的场景,即用户自身有一定运维能力,且业务场景需要用户手动做一些管控比如资源规划、弹性伸缩,甚至自定义一些平台特性以适配业务;相对而言 CCI 适合业务全托管的场景,即用户只需关注以容器形态所交付的应用本身,无需关注资源管控,甚至无需关注 Kubernetes 的相关原理。 第二类服务围绕着 Kubernetes 标准化接口以及结合具体场景的最佳实践来构建完整的应用开发、交付与运维流程,实现云上的应用全生命周期管理。华为云在开发阶段提供微服务开发框架帮助用户在产品开发中落地微服务架构实践,在交付阶段提供“从代码到容器镜像”的自动镜像构建服务,支持一键式部署到 Kubernetes 平台之上,实现持续交付,而最终业务上线运行之后的运维阶段除了基础的容器监控、日志、告警系统之外,同时提供了微服务治理引擎,以及应用性能管理用于故障在线辅助与自动定位。 具体举例而言:[indent] [*]华为云微服务引擎(CSE)提供了具备升降级、容错、熔断等完整服务治理能力的微服务框架,兼容 Spring Cloud、Dubbo 等开源接口,并与 CCE 深度整合,支持 ServiceMesh,未来计划进一步与 CNCF 基金会各微服务相关项目,尤其是 Istio 生态相结合,提供最适合在 K8S 之上运行业务所使用的微服务开发框架 [*]华为云应用编排服务(AOS)提供了以应用为中心的高层编排引擎,能够将 K8S 上运行的各种工作负载、各类资源对象整合管理,并提供了完善的版本与生命周期管理机制,便于客户以更高层的“应用”为对象进行日常交付与运维管理 [*]华为云应用性能管理(APM)提供了丰富的各类运维工具,除了基础的监控、日志与告警,进一步面向故障定位与分析场景提供了应用全局性能拓扑展示与调用链跟踪等高级特性,使得运维人员能够及时了解应用健康状态并进行相关处理。 [/indent] 第三类则是直接在 Kubernetes 之上身体力行地构建一些典型服务化应用,针对某些业务场景提供更易用、更高效的服务,使得客户更聚焦自身业务逻辑。比如:[indent] [*]以分布式数据库(DDM)、分布式缓存(DCS)、分布式消息(DMS)为代表的云化中间件服务,供应用业务逻辑所调用,辅助客户应用的容器化、无状态化、微服务化开发或改造; [*]以 CCE/CCI 为基础设施层所构建的 Serverless Computing(FunctionStage)服务,面向 Event-Driven 的典型业务流场景简化应用代码逻辑,并基于容器热启动、各类主流语言运行时的快速启停优化,实现更高效、更低成本的实时计算; [*]区块链服务 BCS 则提供了主流的 Hyperledger 开源框架,并基于 Kubernetes 的高性能实现 3 分钟一键上链,2000+TPS 的并发区块处理能力,可满足联盟链与私有链的各类业务场景诉求,使客户免运维地使用区块链构建自有业务框架。 未来:紧随社区版本 持续优势创新 纵观华为在 Kubernetes 上的创新可以总结为优势创新、场景创新、技术创新三个层面,优势创新是围绕华为固有的自身强势领域如网络、硬件进行与容器技术的结合运用。场景创新则是聚焦在不同领域的客户需求如游戏、电商、AI 等,基于客户的计算需求进行解决方案的适配。技术创新,以无服务器容器为例,在 Serverless 的云服务趋势下,华为云提供更加便捷,更加全新理念的容器服务方式。目前看来,容器服务并没有统一的服务标准,并没有说哪一种创新可以一招解决所有企业云上容器化的痛点,这需要根据客户的业务场景进行量身匹配,而华为云的全栈容器服务的实践案例也充分说明了这一点。众多不同的容器服务在上线不久已应用在众多不同领域,裸金属容器已成功运用在一部分游戏客户中,帮助其进行测试环境,及高峰时间的流量应对。Windows 容器成功运用在传统 IT 系统的容器化改造,而无服务器容器则可以帮助更多缺乏 Kubernetes 技术投入的公司快速上手享受容器化带来的益处。 这也就是华为云对于 Kubernetes 的一些探索和思考,未来还会有更多基于容器的创新,一切才刚刚开始。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~作者简介 华为云应用服务技术团队,在容器与微服务领域具备长期的技术与实践积累,以领先的容器与微服务等云原生技术专注解决应用上云前后的技术难题,助力企业应用上云更加简单、运行更高效。~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 活动推荐 随着 AI、Big Data、Cloud 的逐渐成熟,FAAS、CAAS 等技术的兴起,以及被运维业务的多样化和复杂化,很多传统的运维技术和解决方案已经不能满足当前运维所需,AIOps 智能运维、大数据运维、ChatOps、SRE、Chaos Engineering、微服务与容器运维等新技术和方向应运而生,它们一方面把最前沿的技术结合到运维中来,一方面在人员角色、领域范围、文化等方面又有了很多扩展,让传统运维有了翻天覆地的变化。来 QCon 北京 2018 与国内外一线技术专家探讨运维前沿技术趋势,及其最佳实践和落地方略。目前大会 9 折报名中,立减 680 元。有任何问题欢迎咨询票务经理 Hanna,电话:010-84782011,微信:qcon-0410。13376 [/indent]
  • [热门活动] 【万千宠爱的1V1专家咨询】来啦!你提问题,产品经理来回答!
    与产品经理对话的问答直通车,各个服务火速直达,为您做了最全整合,马上前往! {:9_88:} 你想不想和大神来一次 “亲密”的技术交流吗?你在产品使用中是否遇到了疑惑?你有不吐不快的话想要向产品经理直接诉说吗?1.微服务云应用平台2. 云容器引擎3.微服务引擎4.函数服务5.应用性能管理服务6.应用运维管理7.应用编排服务8.API网关9.云性能测试服务10.容器镜像服务11.云容器实例直达问题版块发帖提问,产品经理真的会粗线哒哒哒!!! 详细规则请参见各版块,就是简简单单——发帖发帖,没有门槛啦~欢迎回复本帖,表达你们的爱与问候~{:4_87:}