SpringCloud如何创建一个服务提供者provider
前几篇主要集中在注册中心eureka的使用上,接下来可以创建服务提供者provider来注册到eureka。
demo源码见: https://github.com/ryan-miao/spring-cloud-edgware-demo/tree/master/provider-demo
为了方便版本控制,接下来的项目都是基于https://github.com/ryan-miao/spring-cloud-edgware-demo 这个parent配置的。
创建子moudle provider-demo
创建一个子module,项目名叫provider-demo. 填充springboot和springcloud依赖
<dependencies> <!--springboot 依赖start--> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-actuator</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-devtools</artifactid> <optional>true</optional> </dependency> <dependency> <groupid>com.fasterxml.jackson.datatype</groupid> <artifactid>jackson-datatype-jsr310</artifactid> </dependency> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-eureka</artifactid> </dependency> <!--springboot 依赖结束--> <dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger2</artifactid> </dependency> <dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger-ui</artifactid> </dependency> <!--工具类 start--> <dependency> <groupid>com.google.guava</groupid> <artifactid>guava</artifactid> </dependency> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> <optional>true</optional> </dependency> <dependency> <groupid>net.logstash.logback</groupid> <artifactid>logstash-logback-encoder</artifactid> </dependency> <!--工具类end--> </dependencies>
spring-boot-starter-web
提供web能力,必须spring-boot-starter-actuator
提供项目统计和基础的监控endpoint, 想要使用spring-boot-admin监控就必须添加了 spring-boot-devtools
开发模式 jackson-datatype-jsr310
可以解决java8新的时间apilocaldate解体 spring-cloud-starter-eureka
eureka客户端,负责维护心跳和注册 swagger
提供restful契约 lombok
看起来很清爽的编译级别getter setter工具 guava
大而全的java必备类库 logstash-logback-encoder
想要收集日志到elk,使用这个appender
启动类
@enablediscoveryclient @springbootapplication public class providerdemoapplication { public static void main(string[] args) { springapplication.run(providerdemoapplication.class, args); } }
@enablediscoveryclient
来启用服务注册
这个providerdemoapplication应该放置于项目包的最外层,因为@springbootappliatin包含了@componentscan的注解,默认扫描本类包下,否则必须手动指定scan。
swagger
swagger就是一个配置类
@enableswagger2 @configuration public class swaggerconfiguration { private apiinfo apiinfo() { return new apiinfobuilder() .title("服务提供者 api") .description("提供用户信息查询") .termsofserviceurl("") .version("1.0.0") .build(); } /** * 定义api配置. */ @bean public docket api() { return new docket(documentationtype.swagger_2) .select() .apis(requesthandlerselectors.withclassannotation(api.class)) .build() .apiinfo(apiinfo()); } }
对于swagger页面的路由,需要我们来引导下:
创建一个controller来导航
@controller public class homecontroller { @getmapping(value = {"/api", "/"}) public string api() { return "redirect:/swagger-ui.html"; } }
来一个controller 接口
@api @restcontroller @requestmapping("/api/v1/users") public class usercontroller{ private list<user> users = lists.newarraylist( new user(1, "谭浩强", 100, localdate.now()), new user(2, "严蔚敏", 120, localdate.now()), new user(3, "谭浩强", 100, localdate.now()), new user(4, "james gosling", 150, localdate.now()), new user(6, "doug lea", 150, localdate.now()) ); @getmapping("/") public list<uservo> list() { return users.stream() .map(u -> new uservo(u.getid(), u.getname(), u.getage(), u.getbirth())) .collect(collectors.tolist()); } }
一些简单的环境配置
application.yml
spring: application: name: provider-demo jackson: serialization: write_dates_as_timestamps: false default-property-inclusion: non_null #服务过期时间配置,超过这个时间没有接收到心跳eurekaserver就会将这个实例剔除 #注意,eurekaserver一定要设置eureka.server.eviction-interval-timer-in-ms否则这个配置无效,这个配置一般为服务刷新时间配置的三倍 #默认90s eureka.instance.lease-expiration-duration-in-seconds: 15 #服务刷新时间配置,每隔这个时间会主动心跳一次 #默认30s eureka.instance.lease-renewal-interval-in-seconds: 5 server: port: 8082 springfox: documentation: swagger: v2: path: /swagger-resources/api-docs log: path: logs
application-dev.yml
management: security: enabled: false eureka: client: serviceurl: defaultzone: http://localhost:8761/eureka/ logstash: url: localhost:4560
这里需要提一点,由于我集成了logstash, 所以必须安装好logstash, 见elk入门使用。 当然可以跳过,只要不提供logback.xml的配置就行,把依赖中logstash移除即可。
log配置
默认采用logback作为日志框架,简单配置如下,对于不想使用logstash的,移除logstash的appender即可。
在resource下新建logback-spring.xml
<?xml version="1.0" encoding="utf-8"?> <configuration scan="true" scanperiod="60 seconds" debug="false"> <springproperty scope="context" name="appname" source="spring.application.name" defaultvalue="unknown"/> <springproperty scope="context" name="log.path" source="log.path" defaultvalue="logs"/> <springproperty scope="context" name="logstashurl" source="logstash.url" defaultvalue="localhost:4560"/> <include resource="org/springframework/boot/logging/logback/base.xml"/> <!--输出到控制台--> <appender name="console" class="ch.qos.logback.core.consoleappender">logginginterceptor <encoder> <pattern>%d{hh:mm:ss.sss} %x{req.remotehost} %x{req.requesturi} ${appname} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <!--输出到文件--> <appender name="file" class="ch.qos.logback.core.rolling.rollingfileappender"> <rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy"> <filenamepattern>${log.path}/${appname}.%d{yyyy-mm-dd}.log</filenamepattern> </rollingpolicy> <encoder> <pattern>%d{hh:mm:ss.sss} ${appname} %x{req.remotehost} %x{req.requesturi} %x{req.useragent} %x{req.method} - [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <!-- 输出到logstash--> <appender name="logstash" class="net.logstash.logback.appender.logstashtcpsocketappender"> <destination>${logstashurl}</destination> <encoder charset="utf-8" class="net.logstash.logback.encoder.logstashencoder"/> </appender> <springprofile name="dev"> <root level="info"> <appender-ref ref="console"/> <appender-ref ref="file"/> <appender-ref ref="logstash"/> </root> </springprofile> <springprofile name="test, prod"> <root level="info"> <appender-ref ref="file"/> <appender-ref ref="logstash"/> </root> </springprofile> </configuration>
启动
确保eureka已启动,admin最好也启动,方便查看app状态,elk的日志系统也最好可以使用。当然,只有eureka是刚需。
编译打包
mvn clean install package spring-boot:repackage
运行main方法,指定profile为dev, 可以在idea中编辑运行配置,添加参数
--spring.profiles.active=dev
或者命令行jar启动
启动后,访问eureka
访问admin
访问provider-demo
暴露我们的api给consumer
既然有服务提供者,必然是为了consumer消费。consumer应该如何消费?手动调用这个http请求即可。前面提到swagger restful契约,就是服务提供者提供请求访问的参数和要求。consumer如果手动去开发这个client必然耗时,而且容易出错。所以,作为服务提供者,理应提供sdk或者client给consumer来用。
在spring cloud技术体系中,远程调用自然是重中之重。目前我找到的具体用法为feign+ribbon+hystrix.
通过feign的声明式接口对接,实现了consumer对provider的调用。ribbon客户端负载均衡,hystrix作健康熔断。
在这里,我们就首先要提供feign的接口了。
把controller的api提炼成一个接口。首先,我们创建一个新的项目
https://github.com/ryan-miao/spring-cloud-edgware-demo/tree/master/provider-api
将这个项目放到provider-demo的依赖列表里
<!--内部依赖--> <dependency> <groupid>com.test</groupid> <artifactid>provider-api</artifactid> <version>0.0.1-snapshot</version> </dependency> <!--内部依赖end-->
抽离userapi接口道provider-api项目中
@requestmapping("/api/v1/users") public interface userapi { @getmapping("/") list<uservo> list(); }
在provider-demo的controller里改造如下
@api @restcontroller public class usercontroller implements userapi { private list<user> users = lists.newarraylist( new user(1, "谭浩强", 100, localdate.now()), new user(2, "严蔚敏", 120, localdate.now()), new user(3, "谭浩强", 100, localdate.now()), new user(4, "james gosling", 150, localdate.now()), new user(6, "doug lea", 150, localdate.now()) ); @override public list<uservo> list() { return users.stream() .map(u -> new uservo(u.getid(), u.getname(), u.getage(), u.getbirth())) .collect(collectors.tolist()); } }
这样,controller没有变化,只是被抽离了api路径。而独立出来的module provider-api就是我们给consumer提供的client。下一节使用consumer消费。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
SpringCloud如何创建一个服务提供者provider
-
SpringCloud创建服务提供者与消费者
-
如何创建一个tomcat的服务
-
NodeJs中如何创建一个最简单的服务器
-
荐 小名的开源项目【EamonVenti】0.0篇 —— 学习如何搭建一个简单的SpringCloud架构,体验微服务的强大!
-
SpringCloud-服务注册与实现-Eureka创建服务提供者(附源码下载)
-
Kite的学习历程SpringCloud之基于Nacos的服务提供者的创建
-
Laravel如何创建服务器提供者实例代码
-
SpringCloud创建服务提供者与消费者
-
【swoole入门】如何快速创建一个web服务器