SpringCloud学习5-如何创建一个服务提供者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新的时间API LocalDate解体spring-cloud-starter-eurekaeureka客户端,负责维护心跳和注册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启动
java -Xms256m -Xmx1g -XX:+UseG1GC -jar ./target/provider-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
启动后,访问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学习5-如何创建一个服务提供者provider的更多相关文章
- SpringCloud如何创建一个服务提供者provider
SpringCloud如何创建一个服务提供者provider 创建子moudle provider-demo 创建一个子module,项目名叫provider-demo. 填充springboot和s ...
- SpringCloud学习6-如何创建一个服务消费者consumer
上一节如何创建一个服务提供者provider已经启动了一个provider的server,提供用户信息查询接口.接下来,我们启动另一个provider,由于是同一台机器本地测试,我们换一个端口 --s ...
- QT学习之路--创建一个对话框
Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学 ...
- yii学习笔记--快速创建一个项目
下载yii框架 下载地址:http://www.yiiframework.com/ 中文网站:http://www.yiichina.com/ 解压文件
- django examples 学习笔记(1)创建一个独立的python环境
pip install virtualenv 创建一个虚拟环境 virtualenv my_env 创建一个独立的环境 source my_env/bin/activate 激活 ...
- maven 学习---用Eclipse创建一个Maven Web项目
下面是使用 Eclipse 来创建一个Maven Web项目的说明.这是相当简单的. 现在让我们开始吧! 1: 启动 Eclipse, 点击 File->New->Other 2: 在弹出 ...
- Django学习路15_创建一个订单信息,并查询2020年\9月的信息都有哪些
在 app5.models.py 中添加一个 Order 表 class Order(models.Model): o_num = models.CharField(max_length= 16 ,u ...
- DirectX11 学习笔记3 - 创建一个立方体 和 轴
该方案将在进一步的程序 面向对象. 独立的模型类.更像是一个框架. 其中以超过遇到了一个非常有趣的问题,.获得一晚.我读了好几遍,以找到其他的列子.必须放在某些功能Render里面实时更新,而不是仅仅 ...
- SpringCloud学习系列-构建部门微服务提供者Module
1.新建microservicecloud-provider-dept-8001 2.POM <project xmlns="http://maven.apache.org/POM/4 ...
随机推荐
- Vscode调试C的多文件工程配置
关于Vscode的C语言的单文件调试,可以参见VScode调试C语言的设置(win10,Linux),里面已经说明基本的配置和使用. 下面说明一下如何调试多个文件的工程,首先写一个简单的工程,其中工程 ...
- Codeforces 863 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...
- (27)How to stay calm when you know you'll be stressed
https://www.ted.com/talks/daniel_levitin_how_to_stay_calm_when_you_know_you_ll_be_stressed00:12A few ...
- mysql 截取替换某个字符串
SELECT m.content,o.order_price,o.id,m.id FROM scp_home_msg m INNER JOIN scp_order o ON m.link_id=o.i ...
- pointer-events: none 的两个应用场景
简介 pointer-events: none 真是个神奇的属性. 该属性有什么用?借用 CSS3 pointer-events:none 应用举例及扩展 的总结来说: pointer-events: ...
- js 颜色选择插件
COLPICK是一款非常的轻小,无需图片就可以实现颜色选择器的jquery插件,只用 JS 和 CSS 就实现了全部功能,而且非常直观,类似Photoshop的界面,使用方便.颜色的明暗很容易自定义, ...
- Eclipse搭建服务器,实现与Android的简单通信
---恢复内容开始--- 目标:实现客户端(Android App)与服务器(PC)的简单通信 相关准备:eclipse_mars.tomcat8.Android Studio 实现: 1.java环 ...
- python之路(七)-递归算法
递归 特点 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 递归算法解决问题的特点: (1) 递归就是在 ...
- 【转】RPC介绍
转自:http://www.cnblogs.com/Vincentlu/p/4185299.html 摘要: RPC——Remote Procedure Call Protocol,这是广义上的解释, ...
- 手把手教你利用Python自动下载CL社区图片
需求描述: 最近发现CL社区上好多精华的帖子分享的图片非常棒,好想好想保存下来,但是一张一张地保存太费时间了,因此,造物者思想主义的我就想动手写个工具,实现只要输入帖子的链接,就能把所有的精华 ...