前幾篇主要集中在注冊中心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依賴
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啟動
啟動后,訪問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消費。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/woshimrf/p/springcloud-provider.html