前幾篇主要集中在註冊中心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@SpringBootApplicationpublic class ProviderDemoApplication { public static void main(String[] args) { SpringApplication.run(ProviderDemoApplication.class, args); }} @EnableDiscoveryClient來啟用服務註冊
這個ProviderDemoApplication應該放置於項目包的最外層,因為@SpringbootAppliatin包含了@ComponentScan的註解,默認掃描本類包下,否則必須手動指定scan。
Swagger
swagger就是一個配置類
@EnableSwagger2@Configurationpublic 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來導航
@Controllerpublic 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否則這個配置無效,這個配置一般為服務刷新時間配置的三倍#默認90seureka.instance.lease-expiration-duration-in-seconds: 15#服務刷新時間配置,每隔這個時間會主動心跳一次#默認30seureka.instance.lease-renewal-interval-in-seconds: 5server: port: 8082springfox: documentation: swagger: v2: path: /swagger-resources/api-docslog: path: logs
application-dev.yml
management: security: enabled: falseeureka: 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">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"> <rollingPolicy> <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"> <destination>${logstashurl}</destination> <encoder charset="UTF-8"/> </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@RestControllerpublic 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消費。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。