• [技术干货] Spring Boot定义的REST接口使用CSE框架后报告404
    定义了如下接口:  @GetMapping(path = "/v1/user111/ping", produces = MediaType.APPLICATION_JSON_VALUE)   String ping111()   {     return null;   }在Spring Boot下能够正常调用,切换CSE框架后,报告如下错误:o.a.s.c.rest.locator.OperationLocator    : locate path failed, status:Not Found, http method:GET, path:/v1/user111/ping/, microserviceName:user-service出现这个原因是因为这个接口不是public的, CSE约束所有发布为接口的方法,必须是public,而spring boot则没这个限制。 
  • [行业前沿] [学习微服务-第6天] 负载均衡之ServiceComb + SpringCloud Ribbon
    在微服务架构中,客户端负载均衡是指负载均衡器作为客户端软件的一部分,客户端得到可用的服务实例列表然后按照特定的负载均衡策略,分发请求到不同的服务。ServiceComb内置了客户端负载均衡组件,开发者可以非常简单的使用。具体可参考:https://docs.servicecomb.io/java-chassis/zh_CN/references-handlers/loadbalance.html 本文将介绍ServiceComb与SpringCloud的Ribbon负载均衡组件协同工作,以构建微服务应用。ServiceComb已适配对应的接口和配置,用户用极简单的方法配置后即可使微服务应用具备负载均衡的能力。示例以下通过一个服务提供者provider-service和消费者consumer-service作为demo演示。provider-service会启动3个微服务实例,消费者端consumer-service使用Ribbon负载均衡调用proveder-service服务的接口。其中consumer-service在调用provider-service提供的接口时会打印出真实调用的URL ↓↓↓完整示例地址:https://github.com/lisenwork/servicecomb-demo/tree/master/servicecomb-ribbon 预置条件:  示例应先安装启动服务与注册中心ServiceCenter,详细步骤请参考官网↓↓↓http://servicecomb.apache.org/cn/users/setup-environment/#%E8%BF%90%E8%A1%8Cservice-center 一开发服务消费者comsumer-service只需三步即可开发拥有负载均衡能力的微服务步骤如下:01添加依赖新建pom文件,引入如下依赖。完整pom文件内容请参考↓↓↓https://github.com/lisenwork/servicecomb-demo/blob/master/servicecomb-ribbon/consumer-service/pom.xml     02配置 在resources目录下新建ServiceComb配置文件microservice.yaml。配置微服务信息↓↓↓03项目入口新建启动类ConsumerApplication.java。如下图,启动类里同时实例化一个RestTemplate对象。该对象用于后面的服务间接口调用。新建ConsumerController.java。在该类的consumer方法里使用Ribbon的API动态获取服务实例,并打印出被选中的实例的真实IP地址和端口。最后调用服务实例的接口,获取结果并返回。04启动项目根目录下执行命令 mvn spring-boot:run二开发服务提供者provider-service01添加依赖新建pom文件,引入如下依赖。完整pom文件内容请参考↓↓↓https://github.com/lisenwork/servicecomb-demo/blob/master/servicecomb-ribbon/provider-service/pom.xml 02配置 在src/main/resources目录下新建microservice.yaml03项目入口新建启动类ProviderApplication.java新建ProviderController.java。只向外提供/provider接口04启动 服务提供者要启动3个微服务实例。打开microservice.yaml文件,分别修改微服务监听端口为8888,8889,8890,在项目根目录下执行3次命令 mvn spring-boot:run演示浏览器访问http://localhost:7777/consumer,重复刷新一定次数,观察控制台,会发现服务消费者会轮询调用服务提供者的三个实例。小结本文向社区读者从读者角度阐述了ServiceComb是如何支持SpringCloud Ribbon的。我们也非常欢迎爱好者们向社区提问和贡献代码。下章我们将介绍ServiceComb+SpringCloud Ribbon源码篇。如果在阅读代码时有任何疑问想交流,欢迎扫码加入进微信群。期待志同道合的朋友们加入ServiceComb的大门为你们敞开~用心做开源,不忘初衷前期阅读[学习微服务-第5天]ServiceComb+Zipkin源码解读[学习微服务-第4天]ServiceComb+Zipkin[学习微服务-第3天] ServiceComb内置高性能网关服务[每天学习微服务-源码解读] ServiceComb+SpringCloud Zuul[每天学习微服务-网关]ServiceComb+SpringCloud Zuul了解更多信息请访问官方网站http://servicecomb.apache.org/ Github代码仓库https://github.com/apache?q=ServiceComb
  • [技术干货] CSE 和 Spring Boot集成的时候报告Hystrix重复错误
    错误日志:  java.lang.IllegalStateException: Another strategy was already registered.     at com.netflix.hystrix.strategy.HystrixPlugins.registerCommandExecutionHook这个日志是由于spring boot也注册了hystrix,bizkeeper也会注册,hystrix不允许同时注册,但是又没接口能够判断是否已经注册(get方法有bug),所以会打印一个警告。 不影响功能。 如果没有bizkeeper的功能,可以在handler配置里面把他移除。 这样cse就不会尝试注册hystrix了,就没有这个异常了。 默认是这个,如果你们没定制的话:# 处理链配置  handler:    chain:      Provider:        default: qps-flowcontrol-provider,bizkeeper-provider      Consumer:        default: qps-flowcontrol-consumer,loadbalance,fault-injection-consumer,bizkeeper-consumer修改为:# 处理链配置  handler:    chain:      Provider:        default: qps-flowcontrol-provider      Consumer:        default: qps-flowcontrol-consumer,loadbalance,fault-injection-consumer当然也可以打个断点调试下registerCommandExecutionHook方法,看看spring boot 的哪个模块调用了这个方法。 如果不使用spring boot的功能不使用,去掉对应的jar包依赖也是可以的。 
  • [介绍/入门] [每天学习微服务-网关] ServiceComb+SpringCloud Zuul
    在微服务架构模式中后端服务的实例数一般是动态的,于客户端而言很难发现动态改变的服务实例的访问地址信息,服务网关能对用户提供统一的入口。 ServiceComb Java-Chassis 内置了网关服务EdgeService,开发者可以非常简单的搭建一个EdgeService服务。具体可参考:https://docs.servicecomb.io/java-chassis/zh_CN/edge/by-servicecomb-sdk.html 本文将介绍ServiceComb与SpringCloud的Zuul网关组件协同工作,以构建微服务应用。ServiceComb在自身的处理链HandlerTrain中已完成Zuul的对接,用户用极简单的方法配置后即可使微服务应用具备网关服务的能力。为使读者更好地理解,本文将编写一个简单的Hello微服务,并启动2个实例来进行演示。Hello微服务提供hello/{name}接口,只需从前端输入参数name就可从后端微服务获取到程序员百看不厌的Hello world结果。微服务模式下的Hello应用模型技术准备ServiceComb 作为后端微服务核心框架ServiceCenter 作为服务发现与注册中心SpringCloud Zuul 组件做服务网关环境准备以下环境为Windows 64位系统●安装git,详情可参考git安装教程https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git●安装JDK 1.8,详情可参考JDK安装教程。https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html●安装Maven 3.x,详情可参考Maven安装教程https://maven.apache.org/install.htmlServiceCenter安装下载地址:http://mirrors.hust.edu.cn/apache/servicecomb/servicecomb-service-center/1.1.0/下载后解压如下▼在该目录下双击service-center.exe即可启动,命令窗口中出现如下信息基本代表ServiceCenter启动成功,从这个信息也可以得知ServiceCenter监听的是30100端口,等下配置文件要用到。问题点:有可能会有如下信息,这个一般是端口被占用,很可能你打开了两个ServiceCenter,都关闭后再打开就可以了。↓↓↓示例一、后端微服务 HelloService01添加依赖新建maven项目HelloService,pom文件如下02配置新建ServiceComb配置文件src/main/resources/microservice.yaml,内容如下▼03项目入口新建启动类HelloApplication.java,内容如下▼新建Controller类HelloController.java (这里我习惯SpringMvc的叫法,重点看注解)04启动到此,Hello微服务就写完了。这里要启动2个实例。1.先打包,执行mvn clean package2.在项目根目录下target目录下将lib目录和生成的jar包复制到另一个目录中 3.复制jar包,修改其中一个jar包微服务启动端口号为8888(通过WinRar解压缩软件打开jar包并打开microservice.yaml文件修改里面的rest端口号) 4.在当前目录打开两个cmd命令窗口,分别执行命令java -jar HelloService-7777.jar和java -jar HelloService-8888.jar 。此时已经启动了2个微服务实例。二、编写Zuul网关服务01 添加依赖新建maven项目 zuulserver,pom文件如下02配置文件新建springboot配置文件src/main/resources/application.yaml,内容如下新建ServiceComb配置文件src/main/resources/microservice.yaml,内容如下03项目入口新建启动类 ZuulApplication.java新建静态文件 src/main/resources/static/index.html,内容如下 (static目录是按springboot项目规范,属于应用静态文件根目录)04启动到此,网关服务器写完,如下在IDEA里面直接启动应用三. 演示效果浏览器访问http://localhost:8080/ ,如下图。 在输入框中输入姓名,就可以在下面看到打招呼的信息连续点击几次打招呼按钮,可以在启动的2个Hello微服务实例的控制台中看到被调用的信息,如下图(由于这里使用的ServiceComb默认的负载均衡策略 轮询,可见到两个实例都均被调用,关于负载均衡,我们将在后续的文章中解读)。此时用户并不需要关心具体哪个实例被调用了,访问的是哪个后端的实例地址,它只要访问网关就可以了:)总结从以上的示例可以看出,通过 ServiceComb 结合SpringCloud Zuul 实现服务网关功能只需一些简单的配置。后续可以在网关服务上实现统一的鉴权,日志记录,和自定义过滤器等。参考[1] SpringCloud Zuulhttps://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html  [2] ServiceCombhttp://servicecomb.apache.org/cn/docs/quick-start/    
  • [技术干货] Spring Boot场景下启动失败: shouldn't have special char
    2019-01-18 17:12:48.711 ERROR 9456 --- [ntloop-thread-0] o.a.s.config.client.ConfigCenterClient   : Config update from https://cse.cn-north-1.myhuaweicloud.com failed.2019-01-18 17:12:48.711 ERROR 9456 --- [ntloop-thread-0] o.a.s.config.client.ConfigCenterClient   : Server error message is [{"error_code":"SVCSTG.CSE.400607","error_message":"According to the value of 'mutidimen.configKeyFormat', dimensionsInfo ('${spring.application.name}@houseapp#0.0.1') shouldn't have special char '[$, %, ^, &, +, /,  , \\]'"}].这个错误是由于微服务名称错误。 从日志看出,微服务名称是 ${spring.application.name} ,这个是一个place holer。 需要制定这个配置项的值。 
  • [行业前沿] Apache ServiceComb 社区FAQ问答精选(第一期)
    Q:用Postman测试接口可以调通过,swagger-ui页面测试我的接口经常出现connect: connection timed out.A:确认下frontend跟你的应用网络是否通,servicecomb的swagger-ui现在是proxy模式,不是直连Q:准备使用servercomb,下载了center和demo项目,demo项目一直提示ERROR 9868 --- [ntloop-thread-0] o.a.s.s.client.http.RestUtils ......message: Connection timed out求指点A:1.httpaddr/httpport of your service center conf2.service registry address in your microservice.yamlQ:restschema与rpcschema两种方式在性能上有区别吗?A:@RestSchema 注解用于 SpringMVC 和 JAX-RS 两种服务开发风格,而 @RpcSchema 注解用于透明RPC开发风格,这两种注解的差异主要体现在服务端代码开发风格和契约生成模式上。Java-Chassis有一个隐式契约功能,可以让框架根据服务端接口代码自动生成服务契约。由于 SpringMVC 和 JAX-RS 开发风格会在REST接口上打上各种注解,有利于框架生成更符合REST风格的契约;而透明RPC模式由于接口上没有注解,Java-Chassis框架无法确定接口语义以及各个参数在HTTP请求中的位置,因此所有的接口都会作为 POST 接口处理,请求参数都会包装到HTTP请求的body中。这样的契约不太符合REST风格。因此,Java-Chassis更推荐用户使用 @RestSchema 注解开发服务端接口,这样用户只需要写代码,就能让框架自动生成符合REST风格的服务契约。Java-Chassis的传输模型和编程模型是解耦合的。传输模型方面,Java-Chassis支持REST和highway,其中REST又分为以Vert.x作为底层通信框架的REST over Vertx和以Tomcat之类的servlet容器为底层通信框架的REST over Servlet。Java-Chassis的性能主要受传输模型的影响。当用户选择了一个确定的传输模型后,无论他在服务端选择的是哪种编程模型性能都是差不多的。最后,Java-Chassis在客户端代码开发风格上提供了RPC开发模式和RestTemplate开发模式,在其他条件完全相同的情况下,RPC开发模式的性能比RestTemplate高,因此更推荐使用RPC模式编写consumer端代码。http://zhibo.huaweicloud.com/?referVisitorId=oiOYo0XLXIVOMO-ACc9q2cKXGOFQ&c=activity&a=live&id=151108&from=timeline&isappinstalled=0这里视频有说明性能比较数据Q:Caused by: java.lang.IllegalStateException: The schema(id=[calculatorRestEndpoint]) content held by this instance and the service center is different.  You need to increment microservice version before deploying. Or you can configure service_description.environment=development to work in development environment and ignore this error  在bmi例子上做修改,报上面这个错,怎么解决啊?A:这通常是因为你修改了REST接口定义,但是既没有升级微服务版本号,也没有把环境配置成开发环境,所以ServiceComb启动实例检查契约的时候发现契约内容不一致,就报错了。可以考虑升级一下微服务版本号,或者在microservice.yaml文件里面配置一下service_description.environment=development,或者等sc里面的服务实例下线后,把微服务信息删掉重新注册。Q:有谁知道吗?除了注解方式@RequestHeader,还有什么方法可以在Controller中拿到request中的header参数?目前测试发现HttpServletRequest没法拿到A:如果这个Header参数定义在了你的接口契约里,那你的REST接口方法能直接拿到header参数。否则可以扩展一个HttpServerFilter从requestEx参数里面拿header,也可以在你的REST接口里面加上HttpServletRequest参数,从里面拿到headerQ:如何将一个服务部署多个,实现自动减压的?是在配置文件上设置,还是使用其他工具实现。给个链接谢谢。A:https://docs.servicecomb.io/java-chassis/zh_CN/references-handlers/loadbalance.htmlQ:The Service pv-web's instance 62d30daeed5011e8af2f00e081ba3ef7 has been isolated for a while, give a single test opportunity. org.apache.servicecomb.loadbalance.filter.IsolationDiscoveryFilter.allowVisit(IsolationDiscoveryFilter.java:119)?A:你贴出来的日志表示pv-web服务的某个实例被隔离了,现在已经经过了一段时间,Java-Chassis框架在尝试将一个请求路由到该实例,看看它能否被调通,如果调通了的话,这个实例就会从隔离状态恢复过来。https://docs.servicecomb.io/java-chassis/zh_CN/references-handlers/loadbalance.html 请参考这篇文档的“实例隔离功能”。Q:启动ServiceComb-java-chassis项目 sample/codefirst-sample 目录里的 CodeFirstProviderMain,例子程序怎么启动不起来?Caused by: java.lang.NoSuchMethodError: org.apache.commons.lang3.reflect.MethodUtils.getMethodsWithAnnotation(Ljava/lang/Class;Ljava/lang/Class;ZZ)[Ljava/lang/reflect/Method; at org.apache.servicecomb.foundation.common.event.SimpleEventBus.collectSubscribers(SimpleEventBus.java:41) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx.computeIfAbsent(ConcurrentHashMapEx.java:56) at org.apache.servicecomb.foundation.common.event.SimpleEventBus.register(SimpleEventBus.java:51) at org.apache.servicecomb.serviceregistry.task.AbstractTask.<init>(AbstractTask.java:38) at org.apache.servicecomb.serviceregistry.task.AbstractRegisterTask.<init>(AbstractRegisterTask.java:28) at org.apache.servicecomb.serviceregistry.task.MicroserviceRegisterTask.<init>(MicroserviceRegisterTask.java:47) at org.apache.servicecomb.serviceregistry.task.MicroserviceServiceCenterTask.<init>(MicroserviceServiceCenterTask.java:28) at org.apache.servicecomb.serviceregistry.registry.AbstractServiceRegistry.createServiceCenterTask(AbstractServiceRegistry.java:201) at org.apache.servicecomb.serviceregistry.registry.AbstractServiceRegistry.init(AbstractServiceRegistry.java:106) at org.apache.servicecomb.serviceregistry.registry.RemoteServiceRegistry.init(RemoteServiceRegistry.java:54) at org.apache.servicecomb.serviceregistry.RegistryUtils.init(RegistryUtils.java:66) at org.apache.servicecomb.core.CseApplicationListener.setApplicationContext(CseApplicationListener.java:48) at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:121) at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:97) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1622) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.d**ateBean(AbstractAutowireCapableBeanFactory.java:555) ... 13 moreA:用户本地工程的lang3包没有更新到ServiceComb配套的版本,解决方法:1.在用户本地工程的pom.xml点击鼠标右键,选择执行 maven -> reimport2.在用户本地工程的pom.xml点击鼠标右键,选择执行 maven -> Show effective pom,确认其中的lang3是:<dependency>   <groupId>org.apache.commons</groupId>   <artifactId>commons-lang3</artifactId>   <version>3.6</version> </dependency>Q:ServiceComb配置中心支持“配置更新后自动刷新到服务”,如果服务有多个节点,是如何实现的?想来如果是API调用刷新不能确定刷到每个节点,是否cse client端有消息流和配置中心连接呢?类似于企业总线。如果是消息总线,那么业务服务里,需要配置消息总线的url等信息吗?    A:微服务需要配置中心地址。定期pull配置,或者建立websocket链接采用push机制Q:在 ServiceComb-CRM-WorkShop 例子中 边缘服务afterReceiveRequest方法 在调用String userName = template.getForObject("cse://"+USER_SERVICE_NAME + "/validate?token={token}", String.class, token)时候,第一次调用正常后边调用会出现阻塞线程问题,报错:Thread Thread[transport-vert.x-eventloop-thread-4,5,main] has been blocked for 5433 ms, time limit is 2000A:ServiceComb的Edge Service默认工作于高性能的reactive模式,此模式要求工作于Edge Service转发流程中的业务代码不能有任何的阻塞操作。该问题是由于用户业务模型无法满足reactive要求,因此,可以通过修改微服务的配置文件,使用ServiceComb提供的同步线程池模式解决。使用指南可以参考:https://docs.servicecomb.io/java-chassis/zh_CN/edge/by-servicecomb-sdk.htmlQ:spring mvc项目中实现的filter,切换到微服务后,全部不起作用了,是不支持springmvc里边的filter了吗?用户工程同时添加了springboot和provider-springmvc的依赖:<dependency>     <groupId>org.apache.servicecomb</groupId>     <artifactId>spring-boot-starter-provider</artifactId> </dependency> <!-- springmvc支持 --> <dependency>     <groupId>org.apache.servicecomb</groupId>     <artifactId>provider-springmvc</artifactId> </dependency>A:问题原因是因为springmvc和ServiceComb REST是两套不同架构,用户将基于springmvc的项目切换到ServiceComb后,还需要基于ServiceComb REST规则对老的filter做微调,ServiceComb提供相关的架构迁移案例,详情可以参考:1.不同框架之间迁移改造可能工作量的评估指南:https://bbs.huaweicloud.com/blogs/ba7b62178cb811e89fc57ca23e93a89f 可以参考下2.在Spring Boot中使用ServiceComb:https://huaweicse.github.io/cse-java-chassis-doc/using-cse-in-spring-boot/using-cse-in-spring-boot.htmlQ:ServiceComb支持thymeleaf吗?A:这个是个web框架,需要在web容器里面运行,其实和servicecomb是两个完全独立的东西了。servicecomb也支持在web容器里面运行,理论上两个都可以放到一起跑,但我们没用过这个框架。  https://docs.servicecomb.io/java-chassis/zh_CN/build-provider/protocol/rest-over-servlet.htmlQ:原来的那些过滤器都失效了,怎么做才可以既保持原有的能力,又可以把需要发布的接口通过@RestSchema申明出去?A:因为是两个不同的运行时,涉及到“框架内部机制”,而不仅仅是“形式”上的东西。     结合功能,一般都有对应的解决方案的。附上一个简单的不同框架之间迁移改造可能工作量的评估指南: https://bbs.huaweicloud.com/blogs/ba7b62178cb811e89fc57ca23e93a89f 可以参考。 Q:群里有人压过 servicecomb 同步restful 和 spring boot的restful的差距吗?A:网上有很多对比分析,我们也有测试过。一般标准的虚拟机4u8g,差不多分别是5万单位和1万单位。servicecomb restful和其它rpc框架,比如grpc,dubbo,tars等在一个差不多的水准,即5万单位。和调优方式,测试方法不同,会有一些偏差。Q:蓝云上安装了mysql,启动alpha的jar包,直接跑saga源码里的saga-servicecomb-demo,能成功体验事务,照着saga源码里的saga-servicecomb-demo写了个一模一样的工程,是springboot接入servicecomb,调用却出了问题,子事务那边报空指针异常,globalTxId,parentTxId都为null, localTxId有值;自己没找出原因,谁了解这块的帮个忙看下吧,代码地址是:https://github.com/weichao666/sagademoA:saga demo的那个问题解决了,如果使用java chassis1.0.0版本,需要引入guava20.0版本,否则启动报错,注解和调用链正确配置的情况下,使用java chassis1.1.0-SNAPSHOT版本是没问题的,java chassis1.0.0版本使用的guava是19.0Q:ServiceComb中的同步 restful 需要特殊配置吗?A:除edge service之外,ServiceComb的restful默认都是同步的,不需要特殊配置。今天的FAQ精选问题总计20个,可以手动收藏一下哦~And小蜜蜂欢迎来我们社区提问笔芯关注我们~
  • 三分钟迁移Spring boot工程到Serverless
    前言Spring Boot已成为当今最流行的Java后端开发框架,典型的应用方式是在云上购买一台虚拟机,每天24小时在上面运行Java程序,在这种情况下,用户必须维护自己的虚拟机环境,而且按照包月包年等方式进行付费。华为云FunctionGraph(函数工作流服务)有着零运维、低成本计算的特点,FunctionGraph按需运行代码,无需配置和管理主机,您仅需为代码执行的每100ms和次数付费,如果代码没有运行的话,不会产生任何费用,而且每个月还有较多的免费额度。FunctionGraph有明显的成本和维护优势,但是怎样才能把标准的Spring Boot应用程序当做函数在FunctionGraph上运行起来呢?现在以我本地的一个SpringBoot工程(链接https://functionstage-examples.obs.cn-north-1.myhwclouds.com/ServerlessSpringBootDemo.zip)为例展示快速迁移到华为云FunctionGraph的流程。准备工作下载ServerlessSpringBoot2-1.0.0.jar(链接https://functionstage-examples.obs.cn-north-1.myhwclouds.com/ServerlessSpringBoot2-1.0.0.jar);迁移流程1、  制作函数zip包:按照上面的动图添加fgs.properties配置文件,增加两个配置项fgs.component-scan和fgs.mapper-scan,然后导包。 所得的ServerlessSpringBootDemo.zip就是最终的函数代码包。 2、  创建函数:在华为云入口找到FunctionGraph服务,进去后选择创建函数,函数名称建议设置为Controller中的根路径,例如本例的webtest,选择语言为Java8,另外设置函数执行入口为com.huawei.fgs.ext.handler.Main.handler,选择zip包方式上传代码(或者可以将代码先传入OBS桶,使用OBS上传方式创建),创建成功。3、  创建APIG触发器函数创建完成后修改内存为1024,修改超时时间为30(首次启动时间较长)并保存。接下来切换到触发器选项卡,点击创建触发器,选择APIG,将安全认证改成NONE,后端超时设置为30000,和函数超时保持一致,点击确定完成创建。检验结果直接在浏览器中访问APIG生成的URL,因为demo中的Controller中并没有匹配/webtest路径的RequestMapping,因此一开始提示找不到路径,稍加修改后可以看到效果:总结综上所述,整个迁移过程非常简单,用户无需改造自己的业务代码,只需在资源目录下新增fgs.properties文件即可,导包过程和常规情况稍有不同,按照上面的步骤也可以在数秒内完成,最后创建好函数和触发器之后,整个流程就完成了。注意事项1、  使用SpringBoot的AOP特性时,请不要将切面定义到Controller层,否则会导致无法使用;2、  目前Controller都会视作RestController,所有的接口均会以ResponseBody形式返回,暂时不支持返回html页面;3、  在application.properties中去掉server.port配置,加入spring.main.web-environment=false配置项可以小幅提升首次启动速度;4、  如果代码需要经常改动,请将所有的依赖包打包成一个zip,上传到OBS,创建函数时填入依赖代码包的地址,后续更新代码时,只需要上传一个小的jar包即可;5、  如果业务代码中使用了filter,需要对代码进行修改,具体方式后续会提供(本demo中有简单使用例子,依赖FunctionGraph的Java SDK(链接https://functionstage-sdk.obs.myhwclouds.com/java-sdk/fss-java-sdk-1.1.0.zip)中的Runtime-1.1.0.jar和ServerlessSpringBoot2-1.0.0.jar);6、  如果需要使用本demo的代码,请先把application.properties中的mysql信息改为自己的公网访问配置:另外在数据库中创建users表和books表。users表结构如下:books表结构如下:
  • [行业前沿] 能在Spring 3.x上面进行微服务改造吗?
    本帖最后由 木头羊 于 2018-5-30 12:54 编辑如果使用最基本的服务发布的能力,ServiceComb的最小依赖是哪些? 我们项目比较老,希望保持现有的Spring 3.x依赖不动,新增接口通过REST方式注册到service center, 我看到ServiceComb依赖的Spring版本都是4.x+,不知能否基于Spring 3.x版本进行微服务改造?
  • [分享交流] CSE微服务框架提供类似spring security的包吗,谢谢大哥们!
    CSE微服务框架提供类似spring security的包吗,谢谢大哥们!
  • [行业前沿] 使用RPC开发服务和Spring IOC
    我的SimpleServiceImpl中有一个属性,想通过spring iot 注入,该如何实现
  • [问题求助] 使用Spring-Data-MongoDB
    本帖最后由 昵称 于 2018-4-23 10:43 编辑在Spring工程开发中,使用spring-data-mongodb 工具去操作mongodb数据库是非常方便的一种方式。下面我们就在数据库非SSL形式下。以3种配置的方式。去连接mongodb数据库并进行操作演示。本文spring-data-mongodb版本1.8.4.RELEASE, mongodb-driver 版本3.2.2。 简单配置(第一种方式): 1、POM文件中引入依赖: [code] org.springframework.data spring-data-mongodb 1.8.4.RELEASE org.mongodb mongodb-driver 3.2.2 [/code]2、Spring配置文件: config.properties: [code]db.url=mongodb://rwuser:Hello123!@***:8635/hello?authSource=admin [/code]xml: [code] [/code]3、定义一个实体类(带注解): @Document:把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的Collection名字。 @Id:文档的唯一标识,在mongodb中为ObjectId,它是唯一的 @Field:指定保存在mongoDB的名字,感觉类成员名字不好又不想改的时候可以用这个注解。 [code]import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; @Document(collection ="user") public class User { @Id private String id; @Field("name") private String userName; //用户名称 @Field("age") private int userAge;//用户年龄 }[/code] 4、把实体类新增到mongoDB: [code]@Autowired private MongoTemplate mongoTemplateLogDB; public String insert(){ User user = new User(); user.setUserName("wanghuan"); user.setUserAge(1); System.out.println(user.toString()); System.out.println("begin insert"); try { mongoTemplateLogDB.insert(user); }catch (Exception e){ e.fillInStackTrace(); } System.out.println(user.toString()); System.out.println("insert successfully"); return "successfully"; }[/code] 5. 从mongoDB查询新增的的记录: [code]@Autowired private MongoTemplate mongoTemplateLogDB; public String query(){ System.out.println("begin query"); Query query =new Query(); query.addCriteria(new Criteria().orOperator(Criteria.where("name").is("wanghuan"))); List list = mongoTemplateLogDB.find(query, User.class); for (User user: list) { System.out.println("query user :" + user.toString()); } System.out.println("query successfully, list size is " + list.size()); return "successfully"; }[/code] 6. 验证截图: 新增7条数据后,查询结果: 14324 第二种XML配置:(支持) config.properties: [code]db.host=*** db.port=8635 db.database=hello db.credentials=rwuser:Hello123!@admin[/code]xml: [code] [/code]验证截图: 新增8条数据后,查询结果OK: 14325 第三种XML配置:(不支持) config.properties: [code]db.host=*** db.port=8635 db.database=hello db.username=rwuser db.password=Hello123! db.authSource=admin [/code]xml: [code] [/code]验证截图: 在8条数据的基础上,再新增3条数据后,查询结果还是8条,没有添加成功 14326 查询时也报错了: 14327 错误原因分析: 14349 14348 MongoTemplate1.7 以上版本db-factory 中将 authentication-dbname, username, password参数都废弃了,我们MongoTemplate使用的是1.8.4.RELEASE 版本,所以不能再使用这种方式进行连接。应采用 前两种 XML配置的连接方式。
  • [行业前沿] 业务进程spring版本是使用的3系列,怎么解决冲突
    业务进程spring版本是使用的3系列,由于一些原因没办法升级到4,怎么解决与客户端包依赖spring4的冲突。
  • [行业前沿] 配置中心是什么,是Spring Cloud Config么?能力有什么差别?
    RT
  • [行业前沿] 【ServiceComb最全 FAQ】 42个常见问题 大集锦3
    Q: ServiceComb日志替换A: CSE java-chassis日志推荐方式是在启动的时候使用Log4jUtils.init(),直接使用推荐的Log4j来做日志管理,但是有些场景不想用log4j,比如想使用log4j2或者logback,下面以log4j2为例简单介绍下步骤:在代码里面不要使用Log4jUtils.init();去掉log4j的配置文件(不删掉也没关系,因为不会使用);exclude掉CSE框架引入的log4j,例如:<dependency> <groupId>io.servicecomb</groupId> <artifactId>provider-springmvc</artifactId> <exclusions> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> Copy引入log4j2的依赖<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> </dependency> Copy如果没有版本依赖管理,还需要填写上版本号。加入log4j2的配置文件log4j2.xml,关于这个请查看官方说明,例如: <?xml version="1.0" encoding="UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration status="WARN" monitorInterval="30"> <!--先定义所有的appender--> <appenders> <!--这个输出控制台的配置--> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> </console> <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用--> <File name="log" fileName="log/test.log" append="false"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log" filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100 MB"/> </Policies> </RollingFile> <RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log" filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log"> <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100 MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 --> <DefaultRolloverStrategy max="20"/> </RollingFile> <RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log" filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log"> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100 MB"/> </Policies> </RollingFile> </appenders> <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效--> <loggers> <!--过滤掉spring和mybatis的一些无用的DEBUG信息--> <logger name="org.springframework" level="INFO"></logger> <logger name="org.mybatis" level="INFO"></logger> <root level="all"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/> <appender-ref ref="RollingFileWarn"/> <appender-ref ref="RollingFileError"/> </root> </loggers> </configuration> Copy启动服务进行验证Q: netty版本问题A: netty3和netty4是完全不同的三方件,因为坐标跟package都不相同,所以可以共存,但是要注意小版本问题,小版本必须使用CSE的版本。Q: 服务超时设置A: 在微服务描述文件(microservice.yaml)中添加如下配置: cse: request: timeout: 30000 CopyQ: URL 地址就可以唯一定位,为什么要加上一个schema?A:schema 是用来匹配服务契约的,用来保证服务端和消费端契约兼容,每个契约需要一个唯一ID,在服务中心存储。schema映射到java的inte**ce概念,在consumer使用透明rpc模式开发时,可以找到是微服务里的哪个operation。schema之间的方法名是没有唯一性要求的。operation qualified name是治理的key,而URL 因为path参数的存在,没办法直接查找,而qualified name是不会变的。治理是不区分传输的,如果治理按URL 走,那么highway调进来时,还得根据参数反向构造出url,再来正则表达式匹配,太折腾了。http只是一种传输通道,还有别的传输通道不需要映射到URL的。Q: rest客户端调用的时候,实际上只带上了服务名和URL,并不需要指定schema id的, 而实际上根据这个URL也能找到具体契约的,所以指定schema id作用何在?A: 由于透明rpc是接口式调用,并没有URL,内部实际都归一化到operation来描述的,这样就可以结合schema id唯一定位到具体的请求处理中。Q: Transport是个什么概念?用来干什么的?A: transport负责编解码,以及传输。通信模型有rest和highway两种,highway对应的是私有协议,使用protobuf编码,rest用的是json。hightway和rest都是基于vertx做的,vertx是基于netty的。Q: 框架中引入了vertx会有什么好处?A: 启用vertx的标准工作模式更强大,不过对业务人员要求就有些高了,目前还没开放业务接口出来。vertx标准的reactive工作模式,要求业务代码中不能有任何的block wait,sleep,大循环,总之,不能停下来。做到这一点,可以用少很多的CPU,提供更多的服务。Q: 一个服务提供者里面会有多个 appid 和微服务吗?什么场景会出现这种情况?A: 会,这里表达的是一个merge的概念。microservice.yaml文件,可能同时存在于jar,磁盘,命令行参数指定这几个地方,此时他们按优先级合并,是用于增加灵活性的。在jar里的是默认值,在此之外,还有环境变量,命令行参数,配置中心覆盖,提供多层定制。Q: ServiceComb和服务中心是怎么交互的?A: 走rest,主要负责注册,取数据和心跳等;watch事件走websocket,watch事件是观察服务中心实例信息有没有变更。Q: 有类似dubbo那种治理中心吗?A: bizkeeper是一个handler,是治理的其中一个内容。治理可以通过handler扩展。Q: service path怎么理解?A: 每个微服务有一个servicePathManager,每一个schema将自己的path注册进去。Q: 这样浏览器能访问到吗?A: 可以,restful的URL路由,都是由service path搞定。Q: 契约生成时,需要强制带上版本号和语言吗?A: 契约是属于微服务的,微服务本来就有版本,但语言是不应该带上版本号的。应该契约要求与语言无关。契约“没有版本”,契约的版本体现在微服务上,实例能找到所属的微服务的版本,就能找到一个确定的契约。Q: ServiceRegistry里的设计代码和Eureka很类似?A: 我们第一个版本就是在Spring Cloud的基础上做的 后来随着发展发现不够用了才逐渐自己做的一套,所以的确是在充分参考Eureka后设计的。Q: 有些rpc是netty调用redis实现,比直接netty转发优势在哪里?A: 可能是想用redis解决订阅发布吧。但这样意义也不大,之前也尝试过这么用,但后来都改成ServiceComb了。Q: 如果同时引入了transport-rest-servlet和transport-rest-vertx的依赖,那么它怎么决定采用哪一个?A: 如果端口没被占用,就用vertx;如果被占用了,就用servlet。Q: qps流控设计时是出于什么场景考虑的?A: 限流有两个主要作用,第一通过给不同的消费者限流保证对一些重点服务的服务效果,第二防止雪崩效应。可根据服务的重要性来决定水管的粗细,ServiceComb是支持消费端限流和服务端限流两种限流方式的,消费端限流可以做到比较精细的控制。Q: 如果服务端是链式调用,即类似a->b->c,那设置了qps 流控会不会造成水管粗细不均的事情?A: 一般采取的模式是先测量再设置。qps设置最终是结合整体业务需求来进行调控的,而不是就单个节点来进行设置。
  • [行业前沿] 【ServiceComb最全 FAQ】 42个常见问题 大集锦1
    本帖最后由 橘色祥云楼楼主 于 2017-11-13 17:23 编辑Q: ServiceComb和SpringCloud是什么关系,具体的应用场景是什么?A: ServiceComb是华为基于内部多个大型IT系统实践提炼出来的一套微服务开发框架,在开发态基于最佳实践封装了一套微服务运行模型,这些能力对用户完全透明,可以通过配置引入功能和对其进行调整。在运维阶段充分考虑了微服务运维,提供了丰富的监控指标和动态治理能力。 B: ServiceComb的这套能力可以作为一个单独的开发框架,在需要轻量级微服务解决方案的的场景中单独使用,也可以建立在SpringCloud上,与SpringCloud提供的其他组件一起工作,在重量级场景中和SpringCloud一起产生 “1+1大于2”的效果。Q: 用IntelliJ的免费版开发,有什么问题?A: 没有问题,使用IntelliJ 开发,可参考 Setup Developer Environment 进行相应的环境配置。Q: 使用Java-Chassis这个框架时有什么需要注意的地方?A: 使用Java-Chassis有以下这些限制: (1) 0.3.0-SNAPS**之前的版本不支持类似@GetMapping这样的标注。 (2) 所用到的HTTP请求方法一样时,如GET,则方法名不能重载。这是由于生成契约时方法名会作为其Operation ID,所以要保证其唯一性。 (3) 方法和类必须是public的。Q: 使用spring-boot-starter-provider这个依赖时,在application.yml文件中声明的spring.main.web-application属性并没有生效?A: 使用starter-provider这个依赖时,如果用到了servlet这种方式时,需要在application.properties这个文件引入spring.main.web-application=true这样的属性或者在application.yml文件中声明,但是此时需要新建一个application.properties的文件,其内容可以为空。Q: 网关依赖的jar和其他微服务的一样吗? <groupId>io.servicecomb</groupId> <artifactId>spring-boot-starter-provider</artifactId> CopyA: 网关除了要依赖spring-boot-starter-provider之外还要依赖spring-boot-starter-discovery,可以参考LinuxCon-Beijing-Workshop中manager的实现。Q: 网关需要像其他微服务一样配置assembly吗?其中的/maven/gateway这个路径是docker maven plugin默认的吗?A: 需要,由于项目现在使用的是spring-boot的打包方式,docker maven plugin也是依赖打包生成的文件来生成docker镜像的。/maven这个路径是docker maven plugin指定的,而gateway这个路径是在assembly中指定的。Q: 服务接口的返回类型可以是任意类型吗?还是必须是responseEntity?A: 可以,具体可以参考java-chassis的integration-test的实现。Q: 微服务启动后,无法正确调用接口,使用的代码为: @RestController @RestSchema(schemaId = "worker") public class WorkerController { @RequestMapping(value="/count", method=RequestMethod.GET) public int getWorkerNumbers() { ... } } CopyA: 在没有指明根路径的情况下,默认会使用类名作为其根路径,即上述代码中可访问的路径应为/WorkerController/count。如果想要实现/count这样的访问,则要指明根路径: @RequestMapping(value = "/") public class WorkerController {} CopyQ: 如果没有指定RequestMapping这个标注的value时,默认的基本路径是什么?A: 假设你的Controller类名为HelloController,那么基本路径就是/HelloController。Q: 在eclipse下修改了microservice.yaml配置文件下的端口号,启动程序后,端口号没生效?A: 需要单独导入sample项目,如果导入整个ServiceComb-Java-Chassis项目,由于sample目录不在ServiceComb-Java-Chassis模块中,IDE不会对sample进行编译,eclipse下并没有提示错误信息,IDEA下会有提示信息。因此eclipse启动sample的demo会发现修改了端口没有生效。Q: 如何自定义某个Java方法对应的REST接口里的HTTP Status Code?A: 对于正常的返回值,可以通过SwaggerAnnotation实现,例如: @ApiResponse(code = 300, response = String.class, message = "") public int test(int x) { return 100; } Copy对于异常的返回值,可以通过抛出自定义的InvocationException实现,例如:、 public String testException(int code) { String strCode = String.valueOf(code); switch (code) { case 200: return strCode; case 456: throw new InvocationException(code, strCode, strCode + " error"); case 556: throw new InvocationException(code, strCode, Arrays.asList(strCode + " error")); case 557: throw new InvocationException(code, strCode, Arrays.asList(Arrays.asList(strCode + " error"))); default: break; } return "not expected"; } CopyQ: 如何定制自己微服务的日志配置?A: ServiceComb不绑定日志器,只是使用了slf4j,用户可以自由选择log4j/log4j2/logback等等。ServiceComb提供了一个log4j的扩展,在标准log4j的基础上,支持log4j的properties文件的增量配置。默认以规则:”classpath*:config/log4j.properties”加载配置文件实际会搜索出classpath中所有的config/log4j.properties和config/log4j.*.properties, 从搜索出的文件中切出\*的部分,进行alpha排序,然后按顺序加载,最后合成的文件作为log4j的配置文件。如果要使用ServiceComb的log4j扩展,则需要调用Log4jUtils.init,否则完全按标准的日志器的规则使用。Q: 当服务配置了多个transport的时候,在运行时是怎么选择使用哪个transport的?A:ServiceComb的consumer、transport、handler、producer之间是解耦的,各功能之间通过契约定义联合在一起工作的,即: consumer使用透明rpc,还是springmvc开发与使用highway,还是RESTful在网络上传输没有关系与producer是使用透明rpc,还是jaxrs,或者是springmvc开发,也没有关系handler也不感知,业务开发方式以及传输方式consumer访问producer,在运行时的transport选择上,总规则为: consumer的transport与producer的endpoint取交集,如果交集后,还有多个transport可选择,则轮流使用分解开来,存在以下场景:当一个微服务producer同时开放了highway以及RESTful的endpointconsumer进程中只部署了highway transport jar,则只会访问producer的highway endpointconsumer进程中只部署了RESTful transport jar,则只会访问producer的RESTful endpointconsumer进程中,同时部署了highway和RESTful transport jar,则会轮流访问producer的highway、RESTful endpoint如果,此时consumer想固定使用某个transport访问producer,可以在consumer进程的microservice.yaml中配置,指定transport的名称: servicecomb: references: <service_name>: transport: highwayCopy当一个微服务producer只开放了highway的endpointconsumer进程只部署了highway transport jar,则正常使用highway访问consumer进程只部署了RESTful transport jar,则无法访问consumer进程同时部署了highway和RESTful transport jar,则正常使用highway访问当一个微服务producer只开放了RESTful的endpointconsumer进程只部署了highway transport jar,则无法访问consumer进程只部署了RESTful transport jar,则正常使用RESTful访问consumer进程同时部署了highway和RESTful transport jar,则正常使用RESTful访问