SpringCloud如何创建一个服务提供者provider

SpringCloud如何创建一个服务提供者provider

创建子moudle provider-demo

创建一个子module,项目名叫provider-demo. 填充springboot和springcloud依赖

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
< 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

启动类

?
1
2
3
4
5
6
7
8
9
@EnableDiscoveryClient
@SpringBootApplication
public class ProviderDemoApplication {
   public static void main(String[] args) {
     SpringApplication.run(ProviderDemoApplication. class , args);
   }
}

@EnableDiscoveryClient 来启用服务注册

这个ProviderDemoApplication应该放置于项目包的最外层,因为@SpringbootAppliatin包含了@ComponentScan的注解,默认扫描本类包下,否则必须手动指定scan。

Swagger

swagger就是一个配置类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@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来导航

?
1
2
3
4
5
6
7
8
@Controller
public class HomeController {
   @GetMapping (value = { "/api" , "/" })
   public String api() {
     return "redirect:/swagger-ui.html" ;
   }
}

来一个Controller 接口

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

?
1
2
3
4
5
6
7
8
9
10
11
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<? 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是刚需。

编译打包

?
1
mvn clean install package spring-boot:repackage

运行main方法,指定profile为dev, 可以在idea中编辑运行配置,添加参数

?
1
--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的依赖列表里

?
1
2
3
4
5
6
7
<!--内部依赖-->
< dependency >
  < groupId >com.test</ groupId >
  < artifactId >provider-api</ artifactId >
  < version >0.0.1-SNAPSHOT</ version >
</ dependency >
<!--内部依赖end-->

抽离UserApi接口道provider-api项目中

?
1
2
3
4
5
6
@RequestMapping ( "/api/v1/users" )
public interface UserApi {
   @GetMapping ( "/" )
   List<UserVo> list();
}

在provider-demo的controller里改造如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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消费。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微笑点燃希望

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值