• 业务代码抛出异常, CSE微服务引擎将HTTP错误码包装为590非500, 能否关闭这一特性?
  • 华为service mesh使用指南-实现原理
    Mesher集成了注册发现、负载均衡、熔断降级、路由管理、调用链等微服务功能,通过mesher,微服务开发不再依赖开发框架,用户可选择自己习惯的语言,以极低成本进行新的微服务开发,也可以零成本将旧应用微服务化。拓扑cse mesher调用拓扑图来如下,调用关系是:client->server1->server2。我们以server1为例进行分析。server1细节放大后如图所示。Cse Mesher的功能由两个Proxy实现:1,出流量,经过正向代理proxy2,入流量,经过反向代理reverse_proxyProxyMesher接收用户发出的请求,解析用户想要访问的服务,并经负载均衡,路由策略等功能,将请求转发到具体的服务端。当用户将mesher设置为http代理后,用户发出的请求将被mesher接收并转发。例如,用户打算访问server2,rest接口为/hello,则用户的只需发送请求: http://server2/hello,mesher从url中解析出用户打算访问的服务为server2,并从注册中心查询server2的地址,将请求转发至server2。Reverse_proxyMesher接收外部请求,将请求转发至后端的service。工作流程mesher将自己的监听地址注册到注册中心。客户端mesher的Proxy接收用户请求,从注册中心查询服务端的地址,将请求转发至服务端(实际发送到了服务端mesher)。服务端mesher的reverse_proxy接收外部请求,将请求转发到自己的后端。配置若mesher监听在内部ip,如127.0.0.1:30101,mesher将只开启正向代理proxy。由于正向代理proxy只能向外转发请求,因此用户只能发出请求,无法接收请求,即只能作为consumer。cse:   protocols:     http:       listenAddress: 127.0.0.1:30101若mesher监听在外部ip,如192.168.1.1:30101,mesher将同时开启reverse_proxy/proxy,分别监听在192.168.1.1:30101/127.0.0.1:30101(相同端口,不同ip)。由于两个Proxy都开启,mesher可同时作为consumer/provider。cse:   protocols:     http:       listenAddress: 192.168.1.1:30101以上配置位于conf/chassis.yaml文件FAQ问:若要使用mesher,需要用户自己把mesher设置为http代理么?答:是的。用户程序需要将mesher设置为http代理。不同语言设置方法不同,具体的例子可参考《华为service mesh使用指南-快速入门(虚机,windows)》问:mesher接收外部请求,并将请求转发到后端的服务,但mesher怎么知道后端服务的地址?答:mesher读取环境变量SPECIFIC_ADDR作为后端服务地址,例如后端服务监听地址为127.0.0.1:80,则mesher启动前设置环境变量:export SPECIFIC_ADDR=127.0.0.1:80问:每个进程都要绑定一个mesher?答:每启动一个服务进程,就要绑定一个mesher。问:配置mesher时,什么时候监听在内部ip,什么时候监听在外部ip?答:mesher监听在内部ip时,只能作为consumer。监听在外部Ip时,可同时作为consumer/privider。建议都监听在外部ip。问:同一台机器上,能不能启动多个mesher?答:可以。但注意修改监听端口,避免端口冲突。问:mesher默认监听了那些地址?答:mesher默认监听了30101和30102端口,30101是代理/反向代理端口,30102是admin API端口。当修改mesher监听端口时,请避开这些端口。
  • [技术干货] 如何进行微服务的多环境开发部署
    本文内容:介绍微服务的系统结构和隔离关系,为开发人员进行系统规划与微服务设计提供参考。框架介绍:ServiceComb框架定义了一个体系完备的微服务系统结构,通过这个结构可以了解微服务实例间的隔离层次。在微服务系统结构中,顶层是项目(project),项目中的应用分属于不同环境(environment),即测试和生产环境可以分开,每个环境下包含多个应用(application),在某个特定应用的特定环境中,包含多个微服务(service),一个微服务又可以同时存在多个版本(version)。以上,是所有静态元数据的范畴,某个特定服务的特定版本则包含多个在运行时注册上来的微服务实例,因为服务实例的信息在运行时随着系统的伸缩、故障等原因是动态变化的,所以服务实例的路由信息又为动态数据。通过分层管理微服务的这些数据,也就自然而然地实现了实例之间的逻辑隔离。Project对应到华为云上各region下创建的project,不同的project互相隔离,如果该region下没有新建project,则代表该region;例如,在华北区(cn-north-1)下创建一个名字为tianjing的project,若想微服务注册到该project下,可以在microservice.yaml文件里配置:  servicecomb:    credentials:     project: cn-north-1_tianjingEnvironment表示当前微服务实例所属环境,可在microservice.yaml文件里通过service_description.environment配置当前实例环境。Application代表一个软件应用的逻辑实体,表示一个有业务功能呈现给用户的计算机软件应用,可在microservice.yaml文件里通过APPLICATION_ID配置应用名。Service是对按需取用的功能对象的一种描述,一个应用下存在多个服务,各服务间相互调用,可在microservice.yaml文件里通过service_description.name指定服务名。Version表示当前服务的版本,一个服务下可存在多个版本,可在microservice.yaml文件里通过service_description.version配置当前微服务版本号;消费端进行访问时,默认按照路由规则进行访问,可以在消费端通过servicecomb.references.[providerName].version-rule设置版本规则。典型场景:应用间隔离及跨应用调用功能介绍:在ServiceComb框架中,一个应用下包含多个微服务。同一个微服务实例,可以作为公共服务部署到多个应用,通过指定不同的APPLICATION_ID来实现。不同的微服务实例,默认情况下,只允许在同一个应用里相互调用,当用户需要不同应用间的微服务相互调用时,就需要开启跨应用调用功能。配置说明:1.若要开启跨应用调用,首先需在provider端的microservice.yaml文件开启跨应用调用配置。配置项如下:service_description:  properties:   allowCrossApp: true2.Consumer端指定微服务名称调用provider的时候,需要加上provider所属的应用ID,格式由[microserviceName]变为[appID]:[microserviceName]。代码示例:假设consumer所属应用为helloApp,provider所属应用为hellApp2,微服务名称为helloProvider。RestTemplate调用方式当consumer端以RestTemplate方式开发微服务消费者时,需要在调用的URL中将[microserviceName]改为[appID]:[microserviceName],如下:RestTemplate restTemplate = RestTemplateBuilder.create(); ResponseEntity<String> responseEntity = restTemplate.getForEntity(“cse://helloApp2:helloProvider/hello/sayHello?name={name}”, String.class, “ServiceComb”);RPC调用方式当consumer端以RPC方式开发微服务消费者时,声明的服务提供者代理如下:@RpcReference(schemaId = “hello”, microserviceName = “helloApp2:helloProvider”) private Hello hello;跨应用调用与同应用下调用微服务的方式相同:hello.sayHello(“ServiceComb”);典型场景:开发环境互相隔离及快速开发功能介绍:ServiceComb框架通过设置environment,可以将微服务实例标记为开发、测试、预生产、生产环境,实现了在实例级别的天然隔离;客户端在查找服务端实例的时候,只能发现相同environment下的服务端实例。ServiceComb在设计时,严格依赖于契约,所以正常情况下契约变了,就必须要修改微服务的版本。但是如果当前还是开发模式,那么修改接口就是很正常的情况,当修改完毕再次启动当前服务时,新生成的契约和Service Center上保存的旧契约会冲突并报错,导致启动失败,如果每次都通过修改微服务版本号,或者删除该服务在Service Center上的缓存数据来解决,显然对开发人员很不友好。ServiceComb框架支持在开发态进行微服务的快速调试,通过将environment配置为development即可。当接口修改了(Schema发生了变化),重启就可以正常注册到服务中心,而不用修改版本号。但是如果有consumer已经调用了重启之前的服务,那么consumer端也需要重启才能获取最新provider的schema;比如A->B,B接口进行了修改并且重启,那么A这个时候还是使用B之前的schema,调用可能会出错,以免出现未知异常,A也需要重启。配置说明:仅支持以下枚举值:development,testing,acceptance,production,不配置的情况下缺省值为""(空)。方法1:通过JVM启动参数-Dservice_description.environment=development(枚举值)进行设置;方法2:通过microservice.yaml配置文件来指定: service_description:   environment: development方法3:通过环境变量SERVICECOMB_ENV来指定(仅限于windows系统),若是开发态,其值配置为development;典型场景:两地三中心功能介绍:在以两地三中心的解决方案进行跨地区部署服务的场景,同一套服务存在于多个availableZone中,需要实现优先调用同一个AZ内的应用,若本AZ出现问题,要能够访问另一个AZ下的应用,从而保证服务的可靠性。ServiceComb提供了数据中心配置,来实现对微服务的分区和管理。数据中心包含3个属性:servicecomb.datacenter.name, servicecomb.datacenter.region, servicecomb.datacenter.availableZone,数据中心信息不提供隔离能力,微服务可以发现其他数据中心的实例。但是可以通过启用实例亲和性,来优先往指定的区域或者Zone发消息。客户端在路由的时候,会优先将请求转发到zone/region都相同的实例,然后是region相同,但zone不相同的实例,都不相同的时候,则按照路由规则选择一个。亲和性不是逻辑隔离,只要实例之间网络是联通的,那么都有可能访问到;如果网络不通,则会访问失败。在华为云上部署时,可将region和availableZone的值与华为云的region(例如:cn-north-1)和可用区对应起来,但是因为华为云上的不同region目前网络不互通,所以此时不支持跨region访问;除了对应华为云的region值,也可以自行定义其他值,根据实际情况作相应调整,非常灵活。配置说明:servicecomb:  datacenter:   name: mydatacenter   region: my-Region   availableZone: my-Zone小结:本文介绍了使用同一个服务中心时如何管理微服务的方法,如果用户是在华为云上部署微服务,在CSE/ServiceStage的服务治理页面,可以看到各应用分布情况,以及应用里各实例间的互相调用关系,并且显示出各服务实例的环境信息,非常直观,保证用户的良好体验。
  • [热门活动] 华为云微服务Java SDK Maven私服切换至华为开源镜像站通知
    尊敬的华为云客户:华为云计划于2018/10/01 00:00:00将华为微服务引擎Maven私服http://maven.huaweicse.com,正式下线。Maven私服下线后,您将无法下载微服务引擎Java SDK。为避免对您的业务造成影响,建议在私服下线前切换至华为开源镜像站。微服务引擎Java SDK已经在华为开源镜像站上线,欢迎访问https://mirrors.huaweicloud.com/,通过搜索“华为云SDK”或“HuaweiCloud”找到HuaweiCloud SDK,您将可以免费使用CSE、OBS、EI等SDK。更多关于华为微服务引擎CSE的介绍,请您点击了解。如您在使用过程中有宝贵意见,欢迎您拨打华为云服务热线:4000-955-988与我们联系。感谢您对华为云的支持!https://www.huaweicloud.com/notice/2018/20180830175758551.html
  • [技术干货] 如何使用Maven插件将契约文件转换为代码?
    如果您已经有了契约文件,您可以使用以下方式将契约文件转换为代码:进入微服务引擎的公有云界面。在“微服务开发 > 工具下载”页面获取CSE Java SDK,然后解压到本地Maven仓库。将以下内容复制到pom.xml文件中,并进行配置。<plugin><groupId>io.swagger</groupId><artifactId>huawei-swagger-codegen-maven-plugin</artifactId><version>2.2.6</version><executions><execution><goals><goal>generate</goal></goals></execution></executions><configuration><skipOverwrite>true</skipOverwrite><!-- generateAll or generateInterface --><generateLevel>generateAll</generateLevel><!-- specify the swagger yaml --><inputSpecs><param>./src/main/resources/service.yaml</param></inputSpecs><groupId>com.huawei.paas.cse.demo</groupId><artifactId>cse-test</artifactId><packageName>com.huawei.paas.cse.demo.cse-test</packageName><artifactVersion>1.0.0</artifactVersion><output>target/swagger</output><serviceName>demo</serviceName><cseVersion>2.3.35</cseVersion><!-- target to generate --><!--CSE-Java (JAX-RS) | CSE-Java (SpringMVC) | CSE-Java (POJO) --><language>CSE-java (SpringMVC)</language></configuration></plugin><skipOverwrite>表示是否覆盖已存在的文件。<generateLevel>表示生成的形式,支持generateAll和generateInterface两种形式。generateAll表示生成全量工程。generateInterface表示只生成接口定义文件,例如SpringMVC模式,只生成RequestMapping文件。通常最开始的时候需要生成全量工程,后面开发过程中,新增加一个契约文件时,只需要生成接口即可。<inputSpecs>表示契约文件在当前项目的相对路径,支持多契约文件,文件名作为本契约的schemald,如:</inputSpecs><param>./yaml/schema1.yaml</param><param>./yaml/schema2.yaml</param></inputSpecs><output>表示输出路径。<serviceName>为微服务名称,与microservice.yaml文件中的微服务名称相同。<cseVersion>表示CSE Java SDK的版本号。<language>表示指定生成目标开发模式的代码类型,当前支持的代码类型如下:CSE-java (JAX-RS)表示JAX-RS开发模式。CSE-java (SpringMVC)表示SpringMVC开发模式。CSE-java (POJO)表示透明RPC开发模式。<groupId>、<artifactId>和<artifactVersion>三个参数均对应maven工程的坐标。最后执行以下命令生成代码。mvn generate-sources代码生成到output路径下,例如配置为<output>target/swagger</output>,代码会生成在当前项目的target/swagger目录下。
  • [技术干货] 通过rpcschema注册的微服务可以和restschema一样通过对应的端口访问
    可以的。实际上,使用CSE开发, RPC模式、SpringMVC、JAXRS模式都可以出现在一个微服务里面,并存而相互不影响。 当然更多的问这个问题的用户,是想定义了一个服务接口后,微服务客户端可以通过RPC的方式访问服务,然后又能够使用HTTP(比如postman)访问服务。为了满足这个目的,开发者可以使用下面的优秀实践方式:服务端定义服务的时候,定义一个接口;在实现上使用REST(SpringMVC或者JAXRS)开发服务。比如:public interface UserService {    UserInfo getUserInfo(String userName);}@RestSchema(schemaId = "user")@RequestMapping(path = "/")public class UserServiceImpl implements UserService {    @Override    @GetMapping(path = "getUserInfo")    public UserInfo getUserInfo(@RequestParam("userName") String userName) {        return userMapper.getUserInfo(Long.parseLong(userName.substring("user".length())));    }}客户端可以使用RPC的方式调用这个接口。同时可以通过浏览器使用GET方法访问这个服务。 
  • [大咖交流] Istio最佳实践:在Kubernetes上通过Istio服务网格进行灰度发布
    Istio是什么?Istio是Google继Kubernetes之后的又一开源力作,主要参与的公司包括Google,IBM,Lyft等公司。它提供了完整的非侵入式的微服务治理解决方案,包含微服务的管理、网络连接以及安全管理等关键能力,无需修改任何代码就能够实现微服务的负载均衡,服务与服务之间的认证授权以及监控。从整个基础设施角度上看,可以将它理解为PaaS平台上的一个面向微服务管理平台的补充。Istio架构示意图Istio与KubernetesKubernetes提供了部署、升级和有限的运行流量管理能力;利用service的机制来做服务注册和发现,转发,通过kubeproxy有一定的转发和负载均衡能力。但并不具备上层如熔断、限流降级、调用链治理等能力.Istio则很好的补齐了k8s在微服务治理上的这部分能力,同时是基于k8s构建的,但不是像SpringCloud Netflix等完全重新做一套。Istio是谷歌微服务治理上的非常关键的一环。Istio与k8s紧密结合,包括:Sicecar 运行在k8s pod里,作为一个proxy和业务容器部署在一起,部署过程对用户透明。Mesh中要求业务程序的运行感知不到sidecar的存在,基于k8sd的pod的设计这部分做的更彻底,对用户更透明,用户甚至感知不到部署sidecar的这个过程。试想如果是通过VM上部署一个agent,不会有这么方便。Pilot中包含一个controller,通过list/watch kube-apiserver自动发现K8S中的services、endpoints。它通过在Kubernetes里面注册一个controller来监听事件,从而获取Service和Kubernetes的Endpoint以及Pod的关系,但是在转发层面,不再使用kube-proxy转发了,而是将这些映射关系转换成为pilot自己的转发模型,下发到envoy进行转发。K8s编排容器服务已经成为一种事实上的标准;因为微服务与容器在轻量、快速部署运维等特征的匹配,微服务运行在容器中也正成为一种标准实践;对于云原生应用,采用Kubernetes构建微服务部署和集群管理能力,采用Istio构建服务治理能力,将逐渐成为应用微服务转型的标准配置。            自行管理Istio与CCE上使用Istio服务网格的对比华为云 · 云容器引擎CCE(Cloud Container Engine)提供高可靠高性能的企业级容器应用管理服务,支持Kubernetes社区原生应用和工具,简化云上自动化容器运行环境搭建:Ø  简单易用:自动化创建容器集群,一站式部署/运维容器应用,一键式滚动升级;Ø  高性能:自研高性能容器网络,秒级自动弹性伸缩,支持高性能裸金属容器私有集群;Ø  企业级:集群控制面HA和跨AZ高可用,容器应用优雅伸缩,安全下线,保障业务不掉线;Ø  开放兼容:兼容Kubernetes/Docker社区原生版本,CNCF认证的Kubernetes服务提供商,社区的主要贡献者;下列从安装、运行管理和监控多维度对比自建Istio和华为云CCE上使用Istio的差别:自建华为云CCEIstio包管理用户自行下载和管理用户不感知运行配置用户自行配置运行环境和依赖用户不感知Istio安装用户自行探索和安装用户不需要关注具体细节,创建集群时按需启用。Sidecar注入用户自行探索和开发、配置用户不感知Istio升级用户自行探索、开发不影响业务的升级方案提供完整解决方案,按需进行控制面和数据面的升级操作应用调用链用户自行探索、开发和安装、配置对接华为云APM/AOM服务,提供请求调用链跟踪查看能力应用拓扑用户自行探索、开发和安装、配置对接华为云APM/AOM服务,提供查看应用拓扑能力性能监控用户自行探索、开发和安装、配置对接华为云APM/AOM服务,提供请求响应时延的实时性能状态监控云原生应用在CCE上的部署、管理实践云原生应用、云平台与微服务架构云原生应用,是指原生为在云平台上部署运行而设计开发的应用。公平的说,大多数传统的应用,不做任何改动,都是可以在云平台运行起来的,只要云平台支持这个传统应用所运行的计算机架构和操作系统。只不过这种运行模式,仅仅是把虚拟机当物理机一样使用,不能够真正利用起来云平台的能力。云计算平台的核心能力就是提供按需分配资源和弹性计算的能力,而云原生应用的设计理念就是让部署到云平台的应用能够利用云平台的能力实现按需使用计算资源和弹性伸缩。微服务架构是实现企业分布式系统的一种架构模式,即将一个复杂的单体应用按照业务的限定上下文,分解成多个独立部署的组件。这些独立部署的组件,就称为微服务。而在谈论云原生应用与微服务架构关系的时候,根据上下文不同可以从两个角度去看。1) 宏观的云原生应用,即将整个分布式系统看作一个应用,这个角度下,微服务架构是实现云原生应用的一种架构模式;2) 微观的云原生应用,即每个微服务是一个应用,这种语境下,每个微服务要按照云原生应用的设计理念去设计(如我们所熟知的云原生12要素),才能真正实现微服务架构所要达到的目的,即让分布式系统具备按需使用计算资源和弹性伸缩的能力。在华为云CCE容器服务中,我们将宏观的云原生应用,称之为“应用”,而将微观层面的云原生应用,称之为“组件“,用这两个概念来对分布式应用进行管理:图:应用、组件与工作负载的关系在CCE上进行云原生应用管理的实践创建Kubernetes集群            在创建应用前,需要准备好一个Kubernetes集群(1.9及以上版本),并启用Istio服务网格治理。登录CCE控制台,在左侧导航栏中单击“资源管理 > 虚拟机集群”,在“虚拟机集群”界面,单击“创建Kubernetes集群”,按照向导式逐步配置:图1:创建Kubernetes集群图2:使能服务网格,一键式安装Istio并自动使能应用sidecar注入:其他集群创建步骤、配置与已有CCE上创建虚拟机集群一致.创建云原生应用这里我们以Istio开源社区的bookinfo样例应用为例,其包含ProductPage、Reviews、Details、Ratings这4个微服务,拓扑结构以及网络访问信息如下:在CCE左侧导航栏中选择“应用管理”,单击“创建应用”,选择“向导式创建” (后续将支持通过helm模板一键式创建微服务应用以及其流量策略配置,更方便管理),分三大块配置:应用基本信息、网格内组件定义、对外放开路由配置。1、 首先定义应用的基本信息:名称、选择所在集群和namespace:2、 第二步,点击添加组件,按照上方的应用拓扑和网络设计,把组件加入到服务网格:A、添加ratings微服务组件(容器内监听端口为9080,开放至service mesh内部访问端口也配置为9080,后者可根据客户端配置自行调整)1)配置组件基本信息:2)选择负载镜像,并配置版本号为v13) 点击“下一步”,负载高级配置中可以选择配置升级策略、缩容策略、自定义监控等,我们这里不做配置,点击“添加“:可以看到我们为bookinfo添加了一个微服务组件进网格B、 添加reviews微服务组件参考上述添加ratings的步骤,添加reviews:C、 添加details微服务组件参考上述添加组件步骤,添加details微服务组件:D、                添加productpage微服务组件3、 最后,配置应用对外开放的访问路由,从上方拓扑设计可知,productpage作为访问入口:A、点击“添加应用访问方式“B、选择开放至外部访问的组件,并配置开放端口配置后的访问方式信息如下所示:最后点击右下角“创建”,启动应用,在应用列表中可以看到新建的分布式微服务应用bookinfo及其包含的微服务组件:通过应用开放的访问入口访问productpage:在CCE上使用Istio进行灰度发布的实践一键式在集群上启用Istio服务网格集群下应用如果需要做微服务治理,只需要在创建集群时点击启用服务网格即可,不需要自行进行Istio镜像下载、yaml配置、安装、升级等与应用业务无关的复杂基础设施构建工作:开发打包新版本下方我们以开发了一个新版本reviews微服务为例(初始容器镜像版本号为1.5.0),新版本镜像版本号为1.5.0-v2,并且已在本地开发机通过docker push上传至华为云容器镜像服务(SWR):新版本在现在版本基础上增加对ratings微服务的调用,支持评分星星级别展示.发布灰度版本并配置灰度策略现在我们计划通过灰度发布的方式,平滑的在现网升级,在应用列表页面,展开bookinfo下的组件信息,选择reviews微服务组件的“添加灰度版本”:启动灰度版本:配置灰度版本号v2,确认好镜像版本(系统会默认选择最新版本的镜像),点击“启动负载”即可启动灰度版本,容器高级配置已默认继承已有版本观察灰度版本运行状态并配置灰度策略:按照比例分配灰度版本流量比例(这里以20%为例),观察负载启动成功后,点击“提交策略”:回到组件列表可以看到,review微服务已处于灰度发布状态:对review服务进行灰度发布前后的流量对比如下所示:初始版本:灰度状态:如图示,review v2版本调用ratings服务获取星级评价,并将20%流量分流至本版本上访问productpage,可以看到部分请求可以显示星级评价,部分请求仍然是老版本的显示效果(即没有评星这个新特性),并且出现的比例接近1:4.部分访问结果为原有的页面:部分访问结果为带有星级评价特性的页面:持续观测灰度版本运转状态,并进行流量切换接下来,我们会持续观测灰度版本的运行状态,在确认业务处理、性能满足要求后,我们可以选择逐步调大灰度版本的流量比例,而后进一步将流量全部导流至灰度版本上:Ø  观察健康与性能状态:点击CCE左侧导航栏“运维中心”进入AOM服务:选择“指标”->“应用”菜单,持续观察review服务灰度版本v2的健康状态与性能状态:Ø   观察调用链以及请求响应时延:在CCE应用管理中,点击bookinfo应用,查看详情,可以看到CCE服务提供了请求调用链跟踪能力,能够实现分布式异常请求的快速定位(当前提供开源zipkin和grafana能力,后续将对接至华为云AOM服务提供相应能力)可以看到V2版本运转正常,那么下一步我们将逐步扩大流量比,最后将流量全部导至灰度版本,在cce服务中,点击组件名称,进入组件详情页面,点击“接管所有流量”:系统提示会将接管原有版本的所有流量,点击“确定“按钮:现在所有访问reviews的流量都导向v2版本:访问productpage,所有的请求都会呈现星级评价特性:最后,我们将原有老版本(V1)从平台移除:点击确认后,可以看到该微服务只剩下v2版本在运转:通过Istioctl工具进行更多微服务流量治理在上述规则的基础上,cce Istio服务网格还提供了Istioctl命令行工具,实现更全面的流量治理能力,如限流、熔断、连接池管理、会话保持等。进入”资源管理“->“虚拟机集群“,点击所要管理的集群,可以看到Istio命令行的下载和使用指导:  总结华为云CCE容器引擎 + Istio + AOM/APM + SWR服务,提供了完整的云原生应用从开发、部署、上线、监控的完整生命周期管理全栈服务,让企业上云更简单,运行更高效。目前Istio服务网格能力已开放公测,可通过下方链接,快速申请公测,华为云容器服务的专家将全力为您服务,为您的成功保驾护航.申请链接:https://console.huaweicloud.com/cce2.0/?region=cn-north-1#/app/Istio/meshList
  • [行业前沿] 华为消费者云背后的微服务实践经验
    体验请单击微服务引擎。 2018年6月27日,Apache ServiceComb在北京举办主题Workshop,当中,来自华为消费者云的架构师李林锋分享了《ServiceComb在华为消费者云的亿级用户微服务实践》,以下为演讲实录。 讲师介绍:李林锋,华为消费者云应用市场微服务架构师,多年平台中间件、云平台、微服务框架设计和开发经验。工作之余爱好技术写作,《Netty权威指南》和《分布式服务框架原理与实践》作者。  今天分享主要有三个主题,第一个就是服务化的总体的策略,第二个是服务化实践,最后就是业务微服务化以后得到的收益。先自我介绍下,我最早是做业务的,后来从业务转到平台中间件团队做各种平台,包括:短信网关平台、SOA中间件、PaaS平台等。现在在华为终端消费者云业务做云化和微服务化相关架构设计。从业务到平台再回归做业务,感觉还是蛮有意思的。 关于华为消费者云服务简单介绍一下华为消费者云服务,它包括我们经常用到的华为手机应用市场(类似于苹果的APP store),还有我们的智能助手、云空间、天际通等。当然还有一些生活服务相关的,例如视频、音乐、阅读等,这些都属于华为消费者云服务的范畴。我所在的华为应用市场目前是世界第三大应用市场,在全球一百多个国家(支持70多种语言)上线运行。 顶层统一设计今天分享的服务化策略不仅仅单指华为应用市场,还包括了整个华为消费者云服务业务的服务化策略。首先我们看一下整个策略,华为消费者云服务的规模是非常大的,有很多个业务和产品。我们在做服务化设计的时候,最大的一个挑战就是如果能够从顶层统一设计。当一个小团队做服务化的时候,可以采用自底向上的策略。有些技术很强的骨干做技术选型,然后大家就用起来,反正团队人少,业务量也不是很大,最终效果可能还不错。但对华为消费者云服务来说有非常多的团队和业务产品线,如果没有顶层的统一设计,就会造成技术架构选型不一致,这对一个大公司来说成本是非常非常高的。假如要构建一条微服务CI/CD流水线,就要支持所有业务线的所有的异构服务框架,成本很高。因此对于一个体量非常大的业务,一定要有一个顶层的统一设计。我们的技术选型是由架构部跟各个业务产品线设计部一起来完成。这里面比较重要的一点就是顶层统一设计的理念要能够标准化、规范化和工具化,前几年我们也在电信领域做运营商各个系统服务化时,发现在一个大的业务团队去做服务化时,有些架构仅仅存在于架构师的脑海里,下面的整个团队其实并不了解整个服务化的设计理念和思路。这会导致大家认为你是在强推一些东西,或者因为不理解导致实现时走弯路。当大家带着疑问被动去做服务化时,会造成整个团队的割裂,服务化的效果也不会很好。所以在我们设计之处,整体由架设体系来牵头,完成微服务规范的制定、协议选择、流水线建设,以及微服务治理、上线和验收标准。还有一点比较重要的就是组织赋能,因为业务团队是非常大的,业务线又很多,所以要把我们整个服务化的选型以及架构的设计理念,包括我们整个的开发、测试流程以及一整套的CI/CD流水线都是要向设计、开发、测试还有我们的运维人员去讲解。让大家能够充分理解顶层设计和架构思路,防止实现时与架构设计不一致。最后一点就是微服务上线以后,有个服务化地图,就是从组织架构层次来审视和管理微服务,它会包含微服务的SLA指标、微服务流水线地址、微服务重要的治理参数设置、以及微服务业务模型等,方便从更宏观的视角来管控上线的微服务。 没有十全十美的微服务架构,适合的才是最好的选型其实非常非常重要,很多人向我咨询微服务框架选型问题,我也看到很多团队在纠结这个,想选SpringCloud,又感觉gRPC不错,非常纠结。其实对整个服务化选型而言,最重要一点大家一定要明白,就是没有十全十美的微服务架构。现在所有开源出来的,不管是哪个厂商或者组织,都会有优缺点和适应场景,所以说大家不要去陷入一种脱离业务的争论,这种争论其实也会走偏。对我们而言,选型其实也是非常谨慎的,就个人经验,在来华为消费者云服务之前,已经在电信领域做过3到4年的服务化,所以很清楚业务需要什么样的服务框架。只有真正的理解业务的需求,才能够做出好的技术选型。 内外API一致,支持多种服务开发方式 选ServiceComb的一个重要原因就是API的统一和标准化:我们希望微服务内部的API以及对外的(例如对手机端和华为手表,以及对各种各样的设备),API保持一致,方便管理。遵循Open API 2.0/3.0规范也就是支持Swagger API规范的Restful API是非常容易管理的,所以我们这次就果断地选用了Rest API而没用RPC私有协议承载API。微服务的开发方式问题:我们在做微服务化之前,不同团队技术堆栈不同,有用Spring MVC的,也有用Spring Cloud的,还会有一些其他的微服务框架(比如透明RPC方式),我们希望微服务框架能支持多种开发方式,降低业务适配和学习成本。 轻量易集成对于集成,我们倾向于微服务框架支持轻量级的集成。我们现在做微服务化,以重构为主,有一些微服务跑在tomcat容器里,有一些业务做的不太好,绑定了Web的一些技术,因为改造量工作量比较大,所以这个时候希望微服务框架能集成在tomcat里面跑。还有一些是纯后台的业务,不想部署在J2EE容器中,可以更加轻量的部署在Docker容器里面,可能2C4G的资源就能跑起来。 ServiceComb支持vertX的standalone方式(纯后台),还支持跟tomcat这种Web容器集成,正好可以满足我们的业务场景。ServiceComb的轻量级主要体现在两点,第一个就是开发态可以按需引用。假如没用流控,就不需要引流控handler,业务可以做到 ServiceComb的最小化依赖,减小二方库/三方库冲突的风险。第二点就是支持standalone模式,不依赖任何Web容器,对于纯消费端应用,甚至不需要启动监听端口,它的启停速度非常快,特别适合云化之后的容器化部署以及弹性伸缩。    API First—“大家只认接口”我们服务化的一个很重要实践就是API First的落地。不仅仅使用Swagger在线管理API,还有就是服务端和消费端各自基于API定义生成接口和模型,消费端不导入服务端的接口定义类库,实现代码解耦。测试基于API定义生成自动化测试用例(API Test),防止开发人员绕过在线API定义私自修改接口(一旦有不一致修改,接口测试就失败)。设计、开发和测试都只遵循在线的API接口定义,就防止了接口文档与代码、测试用例与代码之间的不一致。 开发模式的选择还有一个就是开发模式,其实开发模式没有好坏之分,像以前我们在做电信服务化的时候,喜欢用透明RPC,消费端会导入服务端的接口定义类库。但是现在在消费云这边我们用的更多是Spring MVC注解,因为业务团队用Spring MVC的比较多,ServiceComb对Spring MVC开发模式是天生支持的,因此改造成本非常低。 我们有些团队以前用的是我们电信软件做的支持电信级的高性能私有的服务框架DSF,更喜欢透明RPC开发模式。当然JAX-RS风格的接口也有。开发模式没有优劣,但是有一点需要强调的就是一定要考虑到开发成本,因为对一个重构项目而言,业务需求要做,还要同时做服务化重构,需要考虑各种成本,包括学习成本、代码重用成本等。 “凡是说性能不重要的都是性能没做好”很多时候大家说云时代或者硬件白菜价的时代,软件的性能就不重要了。但事实上没有哪一家的产品不把性能作为微服务框架竞争力的,所以大家不要相信所谓性能不重要之类的言乱。业务当前不需要这么高的性能并不代表未来也不需要,尤其对于快速发展的互联网业务,如果选型了一个性能不行的架构,后续横向扩展成本会非常高。按照经验,凡是说性能不重要的都是它自身的性能没做好。衡量性能有三个要素:1)吞吐量(QPS)2)时延 3)架构平滑扩展能力。异步非常重要关于线程模型,最重要的一点就要支持异步。像gRPC对异步的支持就非常好,它是基于http /2.0 Stream设计的,http/2.0 Stream支持多路复用,加上异步I/O,很容易构建异步RPC。当前大部分的服务框架不支持异步或者对异步支持不够好,比如有些会返回一个jdk的原生Feature, 很难做比较强大的异步处理。架构原生支持异步是非常重要的。 今年是微服务异步化的元年 以前大家都倾向于先用同步的方式做服务调用,但是上线后发现CPU等资源使用率不高但是性能也上不来,原因是什么?都是同步阻塞式调用惹的祸。异步改造之后,会把大量的资源节省下来,能把机器的cpu和带宽压上去,提升资源的使用率,降低业务的硬件成本。这里澄清一个概念,微服务框架的异步跟I/O的异步是没有任何关系的,举个例子,Tomcat从5.0以后就支持NIO, Servlet规范从3.0才开始支持异步。在此之前,Tomcat的通信I/O是异步了,但是整个http调用是同步的,原因就是Servlet2.X系列接口本身就是同步的。同步服务调用主要有三大缺点:1)资源利用率低2)超时时间比较难设,设置大了容易挂住,设置短了容易超时,比较纠结。3)雪崩效应,如果你的整个调用链上都是同步的,下游节点慢了就阻塞上游,会导致整个调用线程都被阻塞,形成雪崩。我们业务的异步并没有一刀切,因为切异步是有成本的,适合异步的业务才需要切异步。比如说应用分发下载,每天全球有数十亿次的下载或者更新,并发量非常大,而且下载经常集中在某个时间段,流量高,针对这种这种场景就可以做异步优化。 适合异步的场景异步的主要场景有四个:1)降低长流程/复杂业务流程时延:消费端需要调用多个微服务,进行业务逻辑编排,多个微服务之间没有执行先后顺序和参数依赖,可以并行执行。2)性能提升,使用更少的线程处理更多的消息,减少线程的等待时间。设别适用于一些时延敏感型业务3)服务上对服务调用时延不敏感(例如1-3S),如果采用同步调用 + 大超时时间,在业务高峰期,如果时延达到超时阈值,系统很容易被压挂。(单个线程3S完成一次服务调用)。采用异步,则可以按照业务实际要求设置超时时间,不用担心线程资源被挂住4)需要调用多个微服务,希望提升可靠性,不会因为某个微服务处理慢而导致其它微服务调用、以及后续其它业务消息被阻塞,则可以考虑使用异步服务调用异步的收益与挑战业务采用Reactive异步以后带来的收益还是比较大的,带着业务实测性能提升40%多,时延降了30%左右, CPU使用率下降56%,综合性能收益约为2-3倍。业务要做全栈异步实际是非常困难的,会遇到各种挑战。纯Reactive就意味着在整个调用链上不能有同步阻塞操作:1)  同步访问数据库、redis缓存或者对象存储服务。2)  同步的磁盘I/O操作3)  调用第三方SDK,SDK提供的是同步访问接口(例如HttpClient),4)  业务代码的意外阻塞,例如sleep、wait或者长时间的锁等待。第二个难点是异步过程中的上下文的传递,因为大家以前同步写代码的时候,总是喜欢通过类似ThreadLocal线程变量来传递上下文。采用异步之后,只要有线程切换,就要考虑到线程上下文可能会丢失的问题,例如调用链的Trace ID。第三个问题就是异常的传递,同步调用发生异常可以直接在当前调用线程try catch捕获并处理异常。但是当异步切到另一个线程发生异常时,异常是很难传递到调用方线程的,调用方如何更好的处理异步代码块里面抛出的异常,是个难点。最后一个难点就是异步超时控制机制,线程切换之后,超时控制就非常困难了,很多情况下你无法通过调用方超时去中断异步线程的执行。做全栈异步的挑战还是蛮大的,这个不仅仅是微服务框架本身要支持,而且中间件、第三方调用等都需要支持异步,才能达到较好的预期效果。由于Vert.X提供了一个异步生态系统,包含了各种常用开源中间件的SDK,因此基于ServiceComb的异步微服务框架 + Vert.X的各种异步SDK构建全栈异步系统,相对比较容易一些。 关于回调地狱由于接口模型的原因,一些异步框架容易出现回调地狱, ServiceComb当前实现的是JDK 8 Complete Feature,它支持异步操作结果可编排、可组合。这个类库里面提供60个左右常用的方法,每3个一组,实际20个常用的异步接口,可以指定线程池,活着使用jdk的Fork Join Pool,也可以直接在当前线程执行。它具备类似BPM的一些对异步结果做编排的能力,例如对多个异步操作做Join、或、与等,也支持条件判断。异步接口的参数大部分是jdk8的function接口,业务可以直接写Lambda表达式,避免所谓的回调地狱。 接口级隔离舱支持还有一个故障隔离,以前我们做的,比如说Tomcat、Spring MVC架构。如果用同步Spring MVC它的后台用的是Tomcat的Work线程,就是应用在server.xml里面配置的Connector。如果某一个接口或者某个服务慢了以后,它可能会导致整个线程池都被阻塞,这对业务来说是不可接受的。通过ServiceComb的隔离仓技术,可以把快慢不同接口、核心和非核心类接口、管理和租户面接口区分开进行线程池隔离。通过不同维度的隔离舱来实现当某个接口慢或者出了问题以后,把故障严格封闭在某个隔离舱内,防止故障扩散。ServiceComb的隔离仓支持微服务级、接口级和方法级,支持业务自定义隔离线程池,使用起来非常灵活。 微服务治理基于ServiceComb提供的服务治理功能,业务重点构建如下两大能力:1)              线上自动化运维:服务状态检测、容量管理、基于大数据分析的自适应调优、故障诊断、弹性伸缩、故障自动重启、在线迁移等2)              微服务的自治理:服务无状态设计,故障自动切换,Failover失败自动重试 , 故障隔离、大数据分析自动展示系统关键路径、调用依赖画图等 微服务化带来的收益以ServiceComb为核心构建的业务微服务体系,本质还是为了提升业务的研发效率。具体提升点如下:1)上线效率提升:以前业务都是一个大版本(超级war包,也就是所谓的巨无霸的业务),现在拆分成微服务之后各个微服务之间只有API契约依赖,各个微服务独立发版本,迭代周期更快。例如推荐系统服务化之后,各种推荐算法和策略就可以更快的上线验证和优化。 2) 全自动化的微服务流水线:基于ServiceComb业务建立了一套涵盖个人、团队到项目组级别的微服务流水线。每个开发测试都有一套自己的微服务的流水线,这个是个人级的;我们还有微服务团队一级的;业务最终要上线,还是要大家的微服务集成在一起,所以还有个整个项目集成级的流水线。利用微服务流水线,从架构师开始设计API接口、到开发态的静态检查、编译再到打包部署、灰度发布,自动化测试,直到最终微服务上线,全部都是自动化的。3)精细化运维能力提升:利用微服务调用链可以快速的识别业务的关键路径、热点、故障点以及接口依赖,针对特定的故障场景,可以通过服务治理、弹性伸缩、代码架构优化等来保障微服务的高质量线上运行,提升运维能力。以微服务架构为牵引,我们构建了一套适合终端消费者云业务的微服务化体系和团队,通过更好的架构来支撑消费者云业务的全球化发展,为华为终端用户提供更好的服务和体验。详情请点击微服务引擎。
  • [技术干货] [技术交流] 微服务调用,应答返回时报ClassCastException问题的定位
    本文基于CSEJavaSDK-2.3.35版本进行描述,对应的ServiceComb-Java-Chassis版本是1.1.0.B006。文中的示例业务日志和代码来自问题复现demo。问题描述问题复现demo在这里。前几天被拉去看一个问题。某服务(后面称其为A服务)采用同步模式运行,RPC方式调用其他微服务。在本地调试无问题,线上运行时此服务调用另外一个服务(后面称其为B服务)的接口会报错,且通过他们自定义扩展的一个HttpClientFilter的日志来看,被调用的provider服务已经正常返回了应答消息,但是在后面会报ClassCastException,无法将InvocationException转型为业务代码的返回值类型。日志如下:// 业务逻辑被调用 [INFO] test() is called! com.github.yhs0092.blogdemo.javachassis.service.ConsumerService.test(ConsumerService.java:20) // 用户自定义的HttpClientFilter中打印了provider返回的消息 [INFO] get response, status[200], content is [{"content":"returnOK"}] com.github.yhs0092.blogdemo.javachassis.filter.PrintResponseFilter.afterReceiveResponse(PrintResponseFilter.java:26) // ClassCastException被抛出 [ERROR] invoke failed, invocation=PRODUCER rest client.consumer.test org.apache.servicecomb.swagger.invocation.exception.DefaultExceptionToResponseConverter.convert(DefaultExceptionToResponseConverter.java:35) java.lang.ClassCastException: org.apache.servicecomb.swagger.invocation.exception.InvocationException cannot be cast to com.github.yhs0092.blogdemo.javachassis.service.TestResponse at com.sun.proxy.$Proxy30.test(Unknown Source) at com.github.yhs0092.blogdemo.javachassis.service.ConsumerService.test(ConsumerService.java:21) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.servicecomb.swagger.engine.SwaggerProducerOperation.doInvoke(SwaggerProducerOperation.java:160) at org.apache.servicecomb.swagger.engine.SwaggerProducerOperation.syncInvoke(SwaggerProducerOperation.java:148) at org.apache.servicecomb.swagger.engine.SwaggerProducerOperation.invoke(SwaggerProducerOperation.java:115) at org.apache.servicecomb.core.handler.impl.ProducerOperationHandler.handle(ProducerOperationHandler.java:40)分析问题的过程中,他们提到由于线上的B服务还是旧版本的没有升级,于是他们把A服务依赖的B服务的接口jar包替换成了低版本来启动的。分析过程初步接触这个问题给人一种很怪异的感觉。如果一个consumer调用provider时都已经拿到了应答,那么会直接把应答返回给consumer的业务逻辑代码;万一中间真的出错了,那产生的InvocationException也应该是被“抛”出去的,而不是像日志里面显示的那样,尝试“返回”给consumer的业务逻辑才对。可供分析的信息太少了,只能回头看一下sdk代码的相关逻辑,看看能不能复现出这个问题。RPC调用模式的微服务里,业务逻辑通过provider接口做调用时,实际是通过ServiceComb生成的provider接口类型的代理来做调用的。而在这个代理的背后,实际调用流程的源头在org.apache.servicecomb.provider.pojo.Invoker类里面。同步调用模式下,区分应答如何被返回给业务逻辑的关键代码在syncInvoke方法里:protected Object syncInvoke(Invocation invocation, SwaggerConsumerOperation consumerOperation) {   Response response = InvokerUtils.innerSyncInvoke(invocation);   if (response.isSuccessed()) {     // 在这里,response内的result会作为正常应答返回给业务逻辑     return consumerOperation.getResponseMapper().mapResponse(response);   }   // 这里是异常逻辑,response内的result即为错误信息,会被包装为InvocationException抛给业务逻辑   throw ExceptionFactory.convertConsumerException(response.getResult()); }出现了线上日志中的错误说明这个方法没有走到throw语句,而是走return语句那里返回了。InvokerUtils.innerSyncInvoke()方法里触发的主要流程是Handler->HttpClientFilter->网络线程,既然在用户自定义的HTTPClientFilter实现类的afterReceiveResponse()方法中已经打印出了B服务返回的应答消息,那么网络线程部分的嫌疑就可以排除了。问题只可能出在Invoker、Handler、HTTPClientFilter这三块。这个异常需要被catch住并塞到response里。同时,为了让异常作为response body返回,而不是被“抛”出去,response.isSuccessed()需要返回true,这就要求response的Http状态码必须是2xx的。通过在demo中加入自定义的HttpClientFilter,在afterReceiveResponse()方法中抛出一个状态码为200的InvocationException,我们复现出了这个问题,其日志特征与A服务的线上日志一致。根因确定一个response,里面装着一个异常,Http状态码却是2xx的,这个场景应该是不会发生的才对。在向A服务的开发同学确认了他们没有在自定义的Handler、HttpClientFilter内直接操作response后,我们通过日志也无法给出问题结论,只能等A服务的开发同学本地复现问题场景了。好在这个问题本地是能够复现出来的,根因是在于A服务依赖的B服务接口jar包被替换后,旧版本的业务接口应答类型比新版本的多一个属性,而且这个属性的类型是找不到的,大致像下面这样:class ResponseType {   private InnerFieldType someField; // 这里的InnerFieldType会报ClassNotFound }于是当DefaultHttpClientFilter的extractResult()方法尝试将Http body中的json串反序列化为业务代码中的应答对象时,会抛出一个异常,而这个异常被包装成InvocationException后,是被“return”回去的,而不是“throw”出去的,并且这个过程中没有打印任何日志。关键代码在DefaultHttpClientFilter的85-89行:try {   return produceProcessor.decodeResponse(responseEx.getBodyBuffer(), responseMeta.getJavaType()); } catch (Exception e) {   return ExceptionFactory.createConsumerException(e); // 异常被返回 }“return”回去的异常被作为正常的应答对象塞进了response中,而response的状态码是Http应答的状态码——200,于是就有了线上碰到的错误。总结ServiceComb框架在此次定位过程中暴露出来的缺少日志的问题会在后续版本中修复。但是对于开发者而言,更重要的是服务上线部署前需要做好充分验证,临时替换依赖jar包这种简单粗暴的处理方式不可取。那么本地调试过程中碰到这种问题应该如何定位呢?以本文所描述的场景(RPC调用方式,同步运行模式)来看,当业务代码中触发一次微服务调用,ServiceComb的处理流程大致是:Invoker -> InvokerUtils -> Handler -> HTTPClientFilter -> 网络线程Invoker是RPC调用模式下的动态代理,业务代码通过provider接口做调用时,参数首先被传到invoke()方法中。由于consumer工作于同步模式,Invoker会通过syncInvoke()方法调用InvokerUtils的innerSyncInvoke()方法。在这里,Invocation的next()方法被调用,从而触发Handler链执行。在Handler链的末尾是TransportClientHandler,它会调用对应的transport方式发送请求。在Rest over Vertx传输方式下,我们需要关注的是RestClientInvocation的invoke()方法,这里会遍历执行HttpClientFilter的beforeSendRequest()方法,然后将请求调度到网络线程中发送。业务线程此时处于等待返回的状态(SyncResponseExecutor.waitResponse()方法中使用CountDownLatch进行等待)。当请求应答返回后,RestClientInvocation.processResponseBody()方法会将Http response body返回给业务线程处理(通过触发SyncResponseExecutor的CountDownLatch)。应答首先会在RestClientInvocation中遍历HttpClientFilter的afterReceiveResponse()方法进行处理,然后经过Handler链的回调处理,最终返回给InvokerUtils的syncInvoke()方法。其中,Http response body是在DefaultHttpClientFilter的extractResult()方法中反序列化为业务接口返回对象的。这个方法会根据response的HTTP状态码判断如何对待结果,如果是2xx的状态码,则response中的result会作为正常的应答返回给业务逻辑,否则会将result包装到InvocationException中抛给业务逻辑。  // RestClientInvocation中处理应答的关键方法   protected void processResponseBody(Buffer responseBuf) {     invocation.getResponseExecutor().execute(() -> {       // 同步模式下,应答返回流程从这里开始就是在业务线程里执行的       try {         HttpServletResponseEx responseEx =             new VertxClientResponseToHttpServletResponse(clientResponse, responseBuf);         for (HttpClientFilter filter : httpClientFilters) {           // HttpClientFilter处理返回消息体,普通的filter会返回null           Response response = filter.afterReceiveResponse(invocation, responseEx);           if (response != null) { // DefaultHttpClientFilter会把消息体反序列化为应答对象,装入response返回             asyncResp.complete(response); // 通过回调触发handler链             return;           }         }       } catch (Throwable e) {         asyncResp.fail(invocation.getInvocationType(), e); // 包装异常,通过回调触发handler链       }     });   }本地分析这类问题的时候,首先需要知道请求发送的流程,了解RPC动态代理的入口、Handler链的起止点、HttpClientFilter的调用点。这些是流程中的关键节点,根据这些信息可以大致确定问题出现的范围。至于更进一步的定位,就需要大家根据具体的问题进行分析了。看不懂上面说的是什么?正常 :P只看一篇博客是很难弄懂这段流程的。关键的代码节点已经给出来了,自己写个demo调试一下,你的了解会更深刻( ̄▽ ̄)ノ本文转载自【ServiceComb】微服务调用,应答返回时报ClassCastException问题的定位
  • [热门活动] 【7月干货排行榜】应用服务论坛7月都爱看top20
    1 【趁热学:Cloud Native Lives系列直播   第1期】云原生技术的前世今生 https://bbs.huaweicloud.com/forum/thread-9682-1-1.html 2 API网关Demo  https://bbs.huaweicloud.com/forum/thread-9987-1-1.html 3 【降门槛】技术小白也能玩,疯抢华为荣耀V10!  https://bbs.huaweicloud.com/forum/thread-9956-1-1.html4 微服务引擎(CSE)资料汇总  https://bbs.huaweicloud.com/forum/thread-10073-1-1.html5 【每周四技术直播大狂欢】Cloud Native   Lives 每周四晚20:00直播!  https://bbs.huaweicloud.com/forum/thread-9573-1-1.html 6 【3天PPT最全下载】Cloud Native   Days中国巡回Meetup  https://bbs.huaweicloud.com/forum/thread-9462-1-1.html 7 劲爆!一份超全面的APM免费使用指南  https://bbs.huaweicloud.com/forum/thread-9446-1-1.html 8 这个暑假,我们也要大放“价”!  https://bbs.huaweicloud.com/forum/thread-9434-1-1.html 9 全面解析应用运维分布式追踪技术  https://bbs.huaweicloud.com/forum/thread-9457-1-1.html 10 CSE体验馆-体验有感  https://bbs.huaweicloud.com/forum/thread-9448-1-1.html 11 程序员男票秃顶了!我要不要分手?  https://bbs.huaweicloud.com/forum/thread-9455-1-1.html 12 微服务引擎微服务体验馆已上线,欢迎前来围观  https://bbs.huaweicloud.com/forum/thread-9466-1-1.html 13 【AOS最全视频教程】没有用不会的云服务,只有没录好的视频教程! https://bbs.huaweicloud.com/forum/thread-9473-1-1.html 14 go-chassis构建失败求助(已解决)  https://bbs.huaweicloud.com/forum/thread-9479-1-1.html 15 【直播已结束】华为云大咖带你探秘区块链服务  https://bbs.huaweicloud.com/forum/thread-9504-1-1.html 16 华为云微服务半年刊(2018H1)正式发布  https://bbs.huaweicloud.com/forum/thread-9667-1-1.html17 微服务技术领域最新消息播报  https://bbs.huaweicloud.com/forum/thread-9500-1-1.html 18 CPTS电商网站测试方案  https://bbs.huaweicloud.com/forum/thread-9521-1-1.html 19 使用CPTS进行HLS视频压测方案  https://bbs.huaweicloud.com/forum/thread-9546-1-1.html 20 一个文件,两行命令,带你进入研发效率快车道  https://bbs.huaweicloud.com/forum/thread-9668-1-1.html 
  • 【技术交流】从代码机制看AK/SK认证问题
    前言用户开发的微服务要想注册到华为云CSE的服务中心,就需要用到AK/SK认证。由于CSEJavaSDK提供了较多的配置方式,有时候容易出现错配和漏配的情况,本文从CSEJavaSDK读取AK/SK的关键代码入手进行分析,希望能够给大家提供一点AK/SK认证失败时的定位思路。(本文基于CSEJavaSDK-2.3.30进行说明)代码逻辑分析首先需要说明的是,AK/SK也是一个配置项,因此它可以配置在microservice.yaml文件里,可以通过-D设置系统属性来指定,也可以通过环境变量来指定(Windows的环境变量貌似可以带点号.,因此你可以直接在环境变量中指定cse.credentials.accessKey=ak;而Linux的环境变量不能带点,所以不能这么做)。另一方面来说,AK/SK又是一个比较特殊的配置项,因此CSEJavaSDK又提供了一个加密存储的配置方式。无论AK/SK的来源是哪里,最终CSEJavaSDK都是在AKSKManager中完成AK/SK的读取逻辑的。public static Credentials getCredential() throws Exception {   // 读取AK/SK   AKSKOption option = AKSKOption.readAKSK();   // 中间读写缓存等等逻辑忽略……   // 根据cse.credentials.akskCustomCipher配置获取cipher,对AK/SK进行解密     AKSKCipher cipher = (AKSKCipher)CIPHERS.get(option.getAkskCustomCipher());   // 检查逻辑忽略...     char[] ak = cipher.decode(TYPE.AK, option.getAccessKey().toCharArray());     char[] sk = cipher.decode(TYPE.SK, option.getSecretKey().toCharArray());     String project = option.getProject();     if (project == null || project.isEmpty()) {       // 如果用户没有配置cse.credentials.project,就尝试从配置的服务中心地址进行解析,具体的代码忽略……       // 我们平常通过APIGateway连接到服务中心,例如你要连到华北区,配置的地址就是这样的 https://cse.cn-north-1.myhuaweicloud.com       // 可以从中截取出 cn-north-1,这个就是华北区的project       LOGGER.info("The application missing project infomation, so choose a nearest one [{}]", project);     }   return credentials; }以上是AKSKManager的getCredential方法逻辑,可以看到大体的流程是读取AK/SK、根据cse.credentials.akskCustomCipher配置项获取cipher对aksk进行解密、获取cse.credentials.project配置信息。此方法返回的credentials内包含了明文的AK/SK、project信息,因此本地调试时确定AK/SK读取是否有问题的最快途径就是在getCredential方法末尾打断点,查看credentials包含的信息。而在AKSKOption.readAKSK()中读取AK/SK的关键流程如下:public static AKSKOption readAKSK() {   // 从AK/SK加密存储文件读取   AKSKOption option = readFromFile();   if (option == null) {     // 从配置中读取,注意:环境变量、System Property、配置文件都算在这里面     option = buildFromYaml();   }   return option; } private static AKSKOption readFromFile() {   // 忽略缓存逻辑……   // 先尝试从环境变量CIPHER_ROOT中读取加密存储文件的目录     String cipherPath = System.getenv("CIPHER_ROOT");     if (cipherPath == null || cipherPath.isEmpty()) {       // 若不存在则从/opt/CSE/etc/cipher目录中读取       cipherPath = "/opt/CSE/etc/cipher";     }     String certFilePath = cipherPath + File.separator + "certificate.yaml";     File certFile = new File(certFilePath);     if (!certFile.exists() || certFile.isDirectory()) {       // 文件不存在时尝试从系统属性user.dir配置的目录中读取       certFile = new File(System.getProperty("user.dir") + File.separator + "certificate.yaml");       if (!certFile.exists() || certFile.isDirectory()) {         return null;       }     }     AKSKOption option = readFromFile(certFile);     return option; }可以看到CSEJavaSDK优先读取加密存储的AK/SK文件,读不到才去配置中找。而AK/SK加密文件的读取路径优先级从高到低分别是CIPHER_ROOT环境变量配置的目录、/opt/CSE/etc/cipher目录、user.dir系统属性配置的目录(这个少见)。常见问题分析思路当发生AK/SK认证失败的问题时,我们首先需要对问题有个基本的定界,即问题是出在AK/SK读取(解密)上,还是出在AK/SK的内容本身。如果是本地开发调试,那么这个问题很好确定,直接在AKSKManager的getCredential方法里打断点去看一下即可。如果是在线上部署运行的服务,那么只能看日志,凭经验来定位了。与AK/SK认证相关的日志关键词有这些:"read ak/sk from":显示AK/SK的来源是哪里,"read ak/sk from security storage file."表示服务实例从AK/SK加密存储文件中读取配置项的,"read ak/sk from microservice.yaml."表示服务实例从配置项中读物AK/SK的(注意,这里说的是配置项,包含了环境变量、系统属性以及配置文件,不单单是指microservice.yaml文件)。"add ak/sk cipher":加载AKSKCipher,cipher用于解密SK。CSEJavaSDK默认提供的cipher有default、security,default用于明文存储AK/SK的场景,security在AK/SK加密存储场景中使用。CSEJavaSDK使用SPI机制加载cipher,如果发现日志中没有打印加载default和security的内容,那么你就需要检查一下自己依赖的jar包了。"sign request failed ...... OSS_ROOT not properly set":当cipher为security时,CSEJavaSDK会去CIPHER_ROOT环境变量配置的目录里读取解密密钥文件common_shared.key和root.key,如果用户忘记配置CIPHER_ROOT了,就会打印这个错误。"Cipher decode error, will use original as plain!":SK解密失败时会打印此错误日志,常见的错误原因包括CIPHER_ROOT环境变量下没有密钥文件、程序没有权限读取密钥文件、Java没有开启高强度加密功能等。关于Java高强度加密功能,大家去网上搜一下JCE policy能找到解除限制的方法,较低版本的jdk8需要下载一个jce的jar包,高版本的直接修改jre目录下的lib/security/java.security文件配置即可,这个限制只存在于Oracle JDK中,OpenJDK没有此限制。AK/SK或project配置内容错误:当内容配置出错时,实际上AK/SK的读取加密过程并不会报错,只有等到CSEJavaSDK向CSE后端服务(sc/cc/monitor)发送请求时,才会拿到错误返回消息,错误信息包括如下类型:1. AK内容错误:401:Unauthorized, {"errorCode":"401002","errorMessage":"Request unauthorized","detail":"Get service token from iam proxy failed,{\"error\":\"get SK from AK from iam failed. error:Object Not Found - details: \"}"}2. SK内容错误:401:Unauthorized, {"errorCode":"401002","errorMessage":"Request unauthorized","detail":"Get service token from iam proxy failed,{\"error\":\"validate ak sk error\"}"}3. project配置错误:401:Unauthorized, {"errorCode":"401002","errorMessage":"Request unauthorized","detail":"Get service token from iam proxy failed,{\"error\":\"get project token from iam failed. error:http post failed, statuscode: 400\"}"}这些错误内容都是华为云服务的认证鉴权机制返回的,后期如果相关服务升级的话,也许返回的错误内容会有变化。但总之大家可以抓住关键的一点,就是如果前面的AK/SK加载过程都没有报错,只有连接CSE后端服务时拿到401的错误返回,那么你就需要检查一下自己的AK/SK、project是否配置对了。-D启动参数、环境变量、各个microservice.yaml文件都是需要排查的。至于project的配置,可以参考如何查看项目ID。project和你所连接的region是相关的,比如华北区连接的APIGateway地址就是https://cse.cn-north-1.myhuaweicloud.com ,project应该配置为cn-north-1。如果你不配置,CSEJavaSDK会尝试从sc地址中截取出来,但不一定能拿到正确的值,此时启动日志里面会打印提示信息,例如"The application missing project infomation, so choose a nearest one [cn-north-1]",就是在告诉你自动选取的project是cn-north-1。总结博主对AK/SK认证的了解大致也就是上面这些了,很多内容也只能提供一点参考和启发意义。项目实际运行的情况复杂多样,当大家遇到相关问题的时候还是需要根据上面提到的代码逻辑,结合自己服务的实际运行环境去分析,才能更好地定位问题。本文转载自【华为云微服务引擎】从代码机制看AK/SK认证问题
  • [技术干货] 如何排查微服务注册失败问题?
    微服务部署成功后,需要将微服务注册到服务中心和配置中心,才能使用注册发现和微服务治理能力。如果注册失败,可能由于以下因素导致的:AK/SK未配置或者配置不正确。服务中心或配置中心地址配置不正确。网络不通。域名解析失败。监听端口被占用。排查步骤异常消息如下时,问题原因为AK/SK没有正确设置和携带到请求头里。{"errorCode":"401002","errorMessage":"Request unauthorized","detail":"Invalid request, header is invalid, ak sk or project is empty."}检查方法:检查项目中是否依赖如下认证模块(间接依赖也可以,比如项目依赖了cse-solution-service-engine)。<groupId>com.huawei.paas.cse</groupId><artifactId>foundation-auth</artifactId>检查microservice.yaml文件中AK/SK是否配置正确,可以参考下载AK/SK获取正确的AK/SK。cse:credentials:accessKey: your access keysecretKey: your serect keyakskCustomCipher: default异常消息如下时,问题原因为AK/SK配置不正确。{"errorCode":"401002","errorMessage":"Request unauthorized","detail":"Get service token from iam proxy failed,{\"error\":\"validate ak sk error\"}"}检查方法:检查microservice.yaml文件中AK/SK是否配置正确,可以参考下载AK/SK获取正确的AK/SK。cse:credentials:accessKey: your access keysecretKey: your serect keyakskCustomCipher: default异常消息如下时,问题原因为Project配置不正确。{"errorCode":"401002","errorMessage":"Request unauthorized","detail":"Get service token from iam proxy failed,{\"error\":\"get project token from iam failed. error:http post failed, statuscode: 400\"}"}检查方法:检查microservice.yaml文件中Project是否配置正确,可以参考查看项目名获取正确的Project。cse:credentials:accessKey: your access keysecretKey: your serect keyakskCustomCipher: defaultproject: cn-north-1异常消息如下时,问题原因为没有足够的额度增加服务实例。{"errorCode":"400100","errorMessage":"Not enough quota","detail":"no quota to create instance, ..."}检查方法:登录公有云,在微服务引擎概览页面,可以看到实例个数的额度。如果发现有剩余额度,需要检查下代码配置的服务中心地址和区域信息。需要注意的是您需要检查实例所在区域的额度。当微服务链接不上服务中心或者配置中心时,微服务会打印如下信息。由于微服务并没有连上服务中心或配置中心,因此在服务中心或配置中心侧,看不到errorCode异常。Connection refused: no further information检查方法:检查microservice.yaml文件中服务中心和配置中心地址是否配置正确,如果不正确,请配置为正确的地址。cse:service:                  //服务中心信息,其中address为服务中心地址registry:address: https://cse.cn-north-1.myhuaweicloud.cominstance:watch: falseconfig:                   //配置中心信息,其中address为配置中心地址client:serverUri: https://cse.cn-north-1.myhuaweicloud.comrefreshMode: 1refresh_interval: 5000如果服务中心和配置中心地址配置正确,请执行以下命令检查网络是否良好:ping <servicecenter ip>ping <configurationcenter ip>如果能ping通,表示网络良好。说明:当服务中心或配置中心配置的地址为域名时,需要将IP地址修改为域名,再执行ping命令。如果网络良好,执行以下命令获取服务中心或配置中心地址:ping <domain name>系统显示如下,请将获取到的IP地址和域名配置到本地“/etc/hosts”文件中。10.153.78.18   cse.cn-north-1.myhwclouds.com另外,微服务端口号被占用时,微服务可能无法正常启动,可执行如下命令查看服务监控端口是否被占用。netstat -ano | findstr 8080如果端口被其他应用占用,请修改microservice.yaml文件,将端口修改为未被占用的端口。rest:address: 0.0.0.0:8087  //微服务端口,请确保该端口号无冲突
  • [介绍/入门] 微服务引擎CSE产品优势二
    华为云微服务引擎(CSE)首页请到:https://www.huaweicloud.com/product/cse.html华为云微服务引擎(CSE)快速入门:https://support.huaweicloud.com/qs-cse/cse_qs_0001.html了解更多产品信息:https://support.huaweicloud.com/productdesc-cse/cse_productdesc_0001.html
  • [介绍/入门] 微服务引擎(CSE)资料汇总
    微服务引擎(Cloud Service Engine) 提供高性能微服务框架和一站式服务注册、服务治理、动态配置和分布式事务管理控制台,帮助用户实现微服务应用的快速开发和高可用运维;提供Spring Cloud、Service Mesh和ServiceComb商业版。CSE资料汇总类别链接视频CSE灰度发布微服务治理之限流微服务治理之容错微服务治理之熔断微服务治理之降级CSE开发第一个微服务微服务治理之负载均衡入门介绍深入揭秘华为企业级微服务架构的实践之道使用商业版微服务CSE vs 使用开原版微服务Spring Cloud最佳实践快速体验微服务能力基于CSE开发新的微服务基于Mesh接入已有应用容器部署weathermapSpring    Cloud应用如何接入CSE5分钟搞定Dubbo应用接入华为云CSE文档中心产品介绍快速入门常见问题用户指南开发指南事务方案华为云微服务引擎CSE事务方案一:TCC机制的数据最终一致性处理华为云微服务引擎CSE事务方案二:2PC机制的数据强一致性处理相关推荐ServiceComb数据一致性解决方案Saga演进介绍让.NET应用秒变微服务打造一个企业级应用的微服务开发框架(上)---从服务注册中心到服务管理中心打造一个企业级应用的微服务开发框架(下)---ServiceComb通信处理详解商用级Service Mesh服务的设计之道使用ServiceComb Go-chassis构建微服务相关活动华为云微服务引擎CSE大量新特性上线,诚邀您免费体验  
  • [介绍/入门] 微服务引擎CSE产品优势一
    华为云微服务引擎(CSE)首页请到:https://www.huaweicloud.com/product/cse.html华为云微服务引擎(CSE)快速入门:https://support.huaweicloud.com/qs-cse/cse_qs_0001.html了解更多产品信息:https://support.huaweicloud.com/productdesc-cse/cse_productdesc_0001.html
总条数:351 到第 页
上滑加载中