yun-cloud編碼規(guī)范以及編寫指導(dǎo)

編碼規(guī)范

命名

嚴(yán)格遵守java命名規(guī)范

  • 命名采用駝峰式
  • 變量名將擁有一定的含義,要通俗易懂螟炫,杜絕使用含糊不清的變量名稱
  • 其他參照java官方要求進行編碼

注釋

必須提供注釋說明具體的業(yè)務(wù)邏輯知市。可以自行創(chuàng)建intellij注釋模板戈钢。方法包括涝桅,方法注釋,類注釋峻汉, 方法需要寫明具體的用途以及注意事項贴汪。

微服務(wù)命名

項目中的業(yè)務(wù)服務(wù)需要根據(jù)具體的業(yè)務(wù)類型攜帶service脐往,比如user-service, order-service...

編碼注意事項

所有微服務(wù)將完成服務(wù)注冊于發(fā)現(xiàn),不同業(yè)務(wù)之間調(diào)用扳埂,進項使用REST進行內(nèi)部鏈接业簿,不需重復(fù)寫實現(xiàn)邏輯。服務(wù)的拆分本著粗粒度的原則聂喇,盡量避免分布式事務(wù)辖源。

技術(shù)選型

jdk

本次選擇java版本為1.8

spring-cloud

本次使用的spring-cloud版本為Camden.SR4

服務(wù)編寫指南

項目結(jié)構(gòu)初始化將完成基本配置的構(gòu)建(開發(fā)人員了解相關(guān)知識即可蔚携,后續(xù)有時間再深入研究)

  • 配置服務(wù)器(configserver)
  • 服務(wù)注冊器(discovery)
  • 熔斷UI(monitor-dashboard)
  • 授權(quán)服務(wù)器 (auth-service)
  • 路由 (gateway)
  • mysql數(shù)據(jù)庫 (mysql)
  • mongodb數(shù)據(jù)庫(mongodb)

服務(wù)的創(chuàng)建過程

yun-cloud 項目屬于maven項目希太。通過spring-init 創(chuàng)建一個spring-cloud 的pom 項目, 該項目作為根pom酝蜒。微服務(wù)通過new->module->maven-next->service-name 進行maven子項目的構(gòu)建誊辉,創(chuàng)建完成之后src和配置文件都沒有,我們需要修改pom文件亡脑,完善pom信息堕澄,創(chuàng)建SpringApplication程序入口,創(chuàng)建bootstrap.yml 進行服務(wù)器配置文件的加載霉咨。步驟如圖所示:

Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
Paste_Image.png
  • 完善pom信息
Paste_Image.png
Paste_Image.png
Paste_Image.png
  • 創(chuàng)建程序入口
QQ圖片20170114011243.png
  • 創(chuàng)建 bootstrap.yml
Paste_Image.png
  • 創(chuàng)建 服務(wù).yml 比如 user-service.yml 放置到配置服務(wù)器(config)中蛙紫。
Paste_Image.png

tips: bootstrap.yml 為配置文件引導(dǎo)程序,application為應(yīng)用配置途戒,我們更傾向于把應(yīng)用相關(guān)的配置到application.yml中坑傅,比如mysql 等。

配置服務(wù)器的連接

配置服務(wù)器有兩種連接方式:

  • 通過指定配置進行連接
spring:
  application:
    name: statistics-service
  cloud:
    config:
      uri: http://config:8888
  • 通過eureka自動進行配置發(fā)現(xiàn)(自動發(fā)現(xiàn)的前提是config-server的ServerID = configserver,默認(rèn)的配置服務(wù)器如果不填寫application.name 默認(rèn)為configserver)
spring:
  cloud:
    config:
      discovery:
        enabled: true   

開發(fā)人員可以根據(jù)自己需求任選一種方式進行連接喷斋。

注冊發(fā)現(xiàn)的配置

Eureka服務(wù)器已經(jīng)啟動唁毒,我們需要配置注冊到服務(wù)器,并開啟注冊發(fā)現(xiàn)星爪。

  • 引入依賴 (默認(rèn)我們在根pom中已經(jīng)全局引入了starter-eureka)
  • 通過注解進行注冊和發(fā)現(xiàn) 浆西,注解有兩種方式,一種是 @EnableDiscoveryClient 顽腾,另一種是@EnableEurekaClient ,兩者的區(qū)別是近零,discoveryClient實現(xiàn)了許多的服務(wù)發(fā)現(xiàn)方法,比如使用eureka, consul, zookeeper 抄肖,而eurekaClient則是netflix提供的秒赤。兩者選擇一個即可。
  • 修改配置bootstrap.yml 憎瘸,指定注冊服務(wù)器
eureka:
  client:
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/

hystrix-dashboard 的配置

目前入篮,我們將不配置hystrix-dashboard。后期我們通過引入依賴和稍許修改配置文件就可以實現(xiàn)該功能幌甘。詳細(xì)配置可以參考官方教程或者是提供的sample樣例潮售。

授權(quán)服務(wù)器的配置和使用

待更新痊项。。酥诽。

路由配置

我們使用Zuul 作為代理路由服務(wù)鞍泉。

  • Zuul 為唯一對外暴露的端口.

mysql

mysql 我們使用tutumcloud/mysql 提供的鏡像文件進行構(gòu)建.可以cd 到mysql 執(zhí)行docker build -t lvshangke/mysql . 進行手動鏡像的構(gòu)建,也可以通過compose.yml 指定build build ./mysql ,之后可以通過docker命令編譯鏡像,也可以通過docker-compose build 進行編譯肮帐。

mongodb

mongodb 我們使用tutumcloud/mongodb 提供的鏡像進行構(gòu)建,使用版本3.2咖驮,具體用法跟mysql類似,可以參考文檔進行配置也可以參考demo進行使用训枢。

mybatis

我們在拆分微服務(wù)的時候,首先考慮的問題是服務(wù)的顆粒度,設(shè)計方向是,盡量的粗粒度的設(shè)計,避免事務(wù)的集群訪問,關(guān)于涉及到事務(wù)的跨主機問題如果無法避免,則使用JMS實現(xiàn)消息隊列的處理方案.

  • 服務(wù)的粒度直接影響到了服務(wù)之間調(diào)用復(fù)雜度
  • 我們習(xí)慣使用jpa處理表關(guān)系,之后就進行快速的開發(fā)迭代.但是在spring-cloud中,我們并不會首選使用jpa,考慮到JPA涉及到表關(guān)系處理,A業(yè)務(wù)處理用戶基本CURD,B業(yè)務(wù)中處理用戶銀行卡的CURD,如果使用JPA,則A,B表具有重復(fù)的表關(guān)系配置,User,Bank.因為1個用戶有多個銀行卡.這樣的業(yè)務(wù)邏輯設(shè)計就過分的細(xì)粒度.然而一旦使用JPA,無法避免的即使相互依賴,導(dǎo)致上述說的重復(fù)工作,所以我們建議不是必須使用,則首先考慮使用mybatis.
  • 在開發(fā)中,我們維護一套JPA,主要用戶核心業(yè)務(wù)和數(shù)據(jù)庫結(jié)構(gòu)初始化工作(也可以不用)
  • 開發(fā)人員編寫的小業(yè)務(wù),復(fù)雜查詢等,建議使用mybatis來完成數(shù)據(jù)庫操作
    參考資料: mybatis,mybatis-spring-boot-autoconfigure

mybatis 依賴

我們選擇1.2.0版本.

<dependency>
 <groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>

mybatis 配置

mybatis支持注解的配置方式,對于簡單的服務(wù)可以使用該方式,但是我們更傾向于使用xml配置的方式,因為自由度更高,對于一些復(fù)雜查詢,可以更加方便使用.兩種方式都做一些介紹

  • 基于注解
    使用注解@Mapper.使用選擇器 @Select demo

  • 基于xml配置文件
    需要配置mybatis.config-location demo

tips: mybatis

feign

JMS

待更新托修。。恒界。

docker

我們使用docker作為服務(wù)的測試和生產(chǎn)環(huán)境.

docker 開發(fā)環(huán)境

docker 作為開發(fā)環(huán)境的要求以及常見問題:

  • 所有的微服務(wù)創(chuàng)建 src/main/docker/Dockerfile 文件
  • 所有的微服務(wù)中pom 中需要增加maven-docker-plugin插件,并進行統(tǒng)一的配置
  • 項目根目錄創(chuàng)建docker-compose.yml 文件,進行服務(wù)編寫.

tips: 我們通過links 進行容器host關(guān)聯(lián),不過,由于容器啟動順序問題,導(dǎo)致有些服務(wù)器還需要重新啟動才可以,通過使用version 2 中的depends_on 語法替代links, 雖然容器在初始化網(wǎng)絡(luò)中可以按照順序,不過,微服務(wù)中很多需要等待配置服務(wù)器啟動之后才可以調(diào)用配置.容器起來了,應(yīng)用還沒有起來.通過compose.yml 啟動以后,建議使用手動重新啟動下,必須保證配置服務(wù)器在注冊服務(wù)器上已經(jīng)注冊服務(wù). 官方參考中給予了關(guān)于啟動順序的解決方案,depends_on,可以使用wait-for-it,因為我們基于服務(wù)自動發(fā)現(xiàn),所以導(dǎo)致無法正確的監(jiān)聽,在上述服務(wù)器配置中,我們通過主動聲明的方式顯式的指定配置服務(wù)器,之后就可以通過wait-for-it command: ["./wait-for-it.sh","configserver:8888","-t","0","--strict","--","java","-jar","/app/user-service-1.0.jar"] 啟動監(jiān)控,那么,當(dāng)配置服務(wù)器啟動之后將會觸發(fā)微服務(wù)進行啟動.在開發(fā)的過程中可以降低服務(wù)發(fā)現(xiàn)的時間,默認(rèn)的每次心跳為30',我們可以修改eureka.instance.lease-renewal-interval-in-seconds: 1 進行時間壓縮,生產(chǎn)環(huán)境將還原該配置,使用系統(tǒng)默認(rèn)的心跳時間

開發(fā)常用操作

  • 我們通過使用命令進行快速的編譯,通過使用 mvn clean install 進行鏡像的快速構(gòu)建
  • 鏡像構(gòu)建以后,我們通過docker-compose up -d進行啟動
  • 常用的compose 一般有,stop.start,rm,up.
  • 對于局部改動的鏡像,我們可以通過intellij maven工具進行可視化操作.
  • 開發(fā)中我們經(jīng)常使用UI工具作為快速查看容器日志,CURD等操作.

docker 生產(chǎn)環(huán)境

調(diào)試環(huán)境

我們在開發(fā)微服務(wù)時候,將頻繁的修改config,假如頻繁的重新打包鏡像,發(fā)布服務(wù),這樣下來無形中就耽誤了很多時間,

  • 本地安裝docker 環(huán)境
  • 項目初始化 ,執(zhí)行mvn clean install docker-compose up -d,初始化環(huán)境包括,配置服務(wù)器,服務(wù)發(fā)現(xiàn),路由,數(shù)據(jù)庫等.
  • 創(chuàng)建自己的微服務(wù)模塊, 運行Application.因為所有的docker服務(wù)編排已經(jīng)提供了基本的服務(wù),并且對外提供了端口,默認(rèn)開發(fā)環(huán)境中都映射到localhost,比如數(shù)據(jù)庫等等. 我們在開發(fā)測試過程中,可以直接運行自己的微服務(wù),查看服務(wù)是否有問題,及時進行修改.
  • 編寫application.yml 放置在resources中,因為開發(fā)階段需要頻繁的修改該文件,一般情況下這個文件在配置服務(wù)器中,難免會造成時間的浪費,我們通過手動指定,待程序測試通過后,把該文件重命名為服務(wù).yml,放置到config中.
  • 開發(fā)測試沒有問題之后,把配置文件放置在配置倉庫,docker-compose.yml 中進行自己開發(fā)服務(wù)模塊的編寫.
  • 最后提交到git.

tips:在開發(fā)測試階段,盡量的壓縮 鏡像構(gòu)建的時間,避免其他服務(wù)的問題導(dǎo)致開發(fā)時間的延長,所以,建議大家編寫服務(wù)前首先更新git,然后運行一次鏡像,發(fā)布服務(wù), 進行自己服務(wù)的開發(fā)工作, 對于原有服務(wù)的更新,我們建議注釋服務(wù)編排中的該服務(wù),本地啟動待修改的程序進行開發(fā)測試,完成之后再進行修改以及代碼提交.(對于服務(wù)依賴,我們也可以本地啟動多個服務(wù)進行調(diào)試),通過本地運行可以避免構(gòu)建,依賴造成的時間浪費.

安全機制

我們使用oauth2.0作為授權(quán)機制來完成集群的授權(quán)處理.具體的配置如下:

  1. 授權(quán)服務(wù)器
    1.1 引入依賴
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

1.2 Application 中使用@EnableGlobalMethodSecurity(prePostEnabled = true) 開啟全局的方法鑒權(quán),比如使用@PreAuthorize
1.3 編寫授權(quán)服務(wù)器的安全驗證配置

@Configuration
@EnableResourceServer
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .csrf().disable()
            .httpBasic().disable().anonymous().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/info");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user").password("123456").roles("USER").and()
                .withUser("admin").password("123456").roles("USER","ADMIN");
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

安全配置規(guī)則默認(rèn)為所有的連接都需要授權(quán).這里使用默認(rèn)的方式采用內(nèi)存存儲token,初始化測試用戶的時候也是通過配置, 我們在開發(fā)中通過注入service,實現(xiàn)自定義鑒權(quán)處理,主要涉及到的有 UserDetailsService,UserDetails.還需要初始化一個authenticationManagerBean 注意這個 @Bean

1.4 編寫oauth2 配置

@Configuration
@EnableAuthorizationServer
public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {

    private TokenStore tokenStore = new InMemoryTokenStore();

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                    .withClient("mobile")
                    .authorizedGrantTypes("refresh_token", "password")
                    .scopes("api")
                .and()
                    .withClient("user-service")
                    .secret("123456")
                    .authorizedGrantTypes("client_credentials", "refresh_token")
                    .scopes("server");
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(tokenStore)
                .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }
}

oauth2的授權(quán),需要有客戶端鏈接完成請求, 這里分配了多個客戶端鏈接,默認(rèn)我們使用mobile作為移動端api的調(diào)用請求(外部), 其他客戶端作為 服務(wù)之間進行鑒權(quán)的鏈接(內(nèi)部). 外部的鑒權(quán)方式,我們采用password方式,方便api調(diào)用,內(nèi)部采用client_credentials的方式進行鑒權(quán). token我們暫時使用內(nèi)存token,后續(xù)再進行redis的遷移. 這里我們需要忽略的鏈接可以配置到config(WebSecurity web)中.

1.5 配置文件的修改

server:
  context-path: /uaa

默認(rèn)所有的內(nèi)部微服務(wù)都有context-path 假如外部方位 /uaa/test 通過zuul 代理之后,就到了 service/uaa/test.在進行spring-security開發(fā)的過程中,我們一般需要開啟日志

logging:
  level:
    org.springframework.cloud: DEBUG
    org.springframework.security: DEBUG

還有在開發(fā)過程中,一旦開啟了DEBUG,需要控制下eureka心跳時間,要不然日志特別多,不好定位問題.

1.6 配置zuul 代理
因為文檔上面說application 加上@EnableOAuth2Sso @EnableZuulProxy 就可以開啟token轉(zhuǎn)發(fā),我們就按要求配置下, 實際情況是 好像沒什么用.
作為對外的zuul ,我們這里可以按照上面1.3的方式給他單獨配置一個安全過濾器,不過作為對外提供的端口,我們這里不做安全控制, 所有的校驗機制交給鑒權(quán)服務(wù)器去處理.

  routes:
    auth-service:
        path: /uaa/**
        url: http://localhost:8084

    account-service:
        path: /user/**
        serviceId: user-service

我們定義一個轉(zhuǎn)發(fā)規(guī)則. zuul這里我們就配置spring-security了,我們開放這個微服務(wù), 允許訪問的連接進行代理配置即可

1.7 微服務(wù)編寫
微服務(wù)相當(dāng)于一個小應(yīng)用, 這里可以配置微服務(wù)自己的安全機制,參考上面的1.3.進行自己服務(wù)的連接處理,可以忽略一些連接,也可以驗證一些連接.我們先看配置,具體的流程下面再整理
我們通過

@SpringBootApplication
@EnableOAuth2Client
@EnableEurekaClient
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class UserApplication {

    public static void main(String [] args){
        SpringApplication.run(UserApplication.class, args);
    }

我們按照上面的配置方法,開啟全局方法驗證,開啟Oauth2Client. 之后編寫自己服務(wù)的安全控制.

@Configuration
@EnableResourceServer
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .csrf().disable()
            .httpBasic().disable();
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

這里測試使用全部需要授權(quán)才能訪問. 假如用戶已經(jīng)獲取到token, 訪問該資源,該資源又要去鑒權(quán)服務(wù)器查看是否正確. 默認(rèn)我們內(nèi)部的訪問為"server"通過客戶端鑒權(quán),查看token的合法性. 所以這里需要注入幾個bean

@Bean
    @ConfigurationProperties(prefix = "security.oauth2.client")
    public ClientCredentialsResourceDetails clientCredentialsResourceDetails() {
        return new ClientCredentialsResourceDetails();
    }

    @Bean
    public RequestInterceptor oauth2FeignRequestInterceptor(){
        return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), clientCredentialsResourceDetails());
    }

    @Bean
    public OAuth2RestTemplate clientCredentialsRestTemplate() {
        return new OAuth2RestTemplate(clientCredentialsResourceDetails());
    }

通過@Configuration進行注入.
1.8 微服務(wù)的配置

security:
  oauth2:
    client:
      clientId: user-service
      clientSecret: 123456
      accessTokenUri: http://localhost:8084/uaa/oauth/token
      grant-type: client_credentials
      scope: server
    resource:
      user-info-uri: http://localhost:8084/uaa/me

注意user-info-uri,當(dāng)用戶實際已經(jīng)獲取token,則訪問該資源,該資源會去查看是否已經(jīng)被鑒權(quán)服務(wù)器認(rèn)證, 我們在auth-service 中需要創(chuàng)建一個controller

@RequestMapping("/me")
    public Principal getCurrentLoggedInUser(Principal user) {
        return user;
    }

1.9 使用
我們開放了zuul作為對外暴露的端口, 當(dāng)用戶通過zuul訪問資源時候,每個資源都屬于一個微服務(wù),每個微服務(wù)都是一個spring項目,都有自己的一套驗證機制,是否需要鑒權(quán)呀? 如果需要, 則用戶沒有權(quán)利就收到反饋結(jié)果, 用戶需要申請一個token

申請token: localhost:8080/uaa/oauth/token
請求類型: POST
參數(shù): username ,password, grant_type, scope(選填)
請求頭: Authorization: Basic bW9iaWxlOg== (這里的Basic 后面跟的是mobile:的base64編碼方式,代表請求的客戶端為mobile,密碼為空)

用戶一旦申請了token 在遇到一些需要授權(quán)的連接的時候就可以攜帶該token

請求: localhost/user/
類型: GET
請求頭: Authorization: Bearer $token

我們可以通過log日志查看整體的流程, 通過token訪問zuul, zuul轉(zhuǎn)發(fā)到對應(yīng)的微服務(wù),是否有安全配置, 一層層過濾器下來,用戶通過userinfouri訪問鑒權(quán)服務(wù)器,(攜帶client: user-service,password:,scope:) ,鑒權(quán)服務(wù)器查看client是否合法,完成鑒權(quán).

jenkins自動化構(gòu)建

監(jiān)控系統(tǒng)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睦刃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子十酣,更是在濱河造成了極大的恐慌涩拙,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耸采,死亡現(xiàn)場離奇詭異兴泥,居然都是意外死亡,警方通過查閱死者的電腦和手機虾宇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門搓彻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人文留,你說我怎么就攤上這事好唯。” “怎么了燥翅?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵骑篙,是天一觀的道長。 經(jīng)常有香客問我森书,道長靶端,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任凛膏,我火速辦了婚禮杨名,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猖毫。我一直安慰自己台谍,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布吁断。 她就那樣靜靜地躺著趁蕊,像睡著了一般坞生。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掷伙,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天是己,我揣著相機與錄音,去河邊找鬼任柜。 笑死卒废,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宙地。 我是一名探鬼主播摔认,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绸栅!你這毒婦竟也來了级野?” 一聲冷哼從身側(cè)響起页屠,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤粹胯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辰企,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體风纠,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年牢贸,在試婚紗的時候發(fā)現(xiàn)自己被綠了竹观。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡潜索,死狀恐怖臭增,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竹习,我是刑警寧澤誊抛,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站整陌,受9級特大地震影響拗窃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泌辫,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一随夸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧震放,春花似錦宾毒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邪锌。三九已至,卻和暖如春癌瘾,著一層夾襖步出監(jiān)牢的瞬間觅丰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工妨退, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留妇萄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓咬荷,卻偏偏與公主長得像冠句,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子幸乒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理懦底,服務(wù)發(fā)現(xiàn),斷路器罕扎,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • 原文:https://dzone.com/articles/microservice-architecture-w...
    Oopsguy閱讀 1,808評論 1 15
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,809評論 6 342
  • 沒有最喜歡的顏色 沒有最喜歡的衣服 但有最快樂的我 追著蝴蝶 跑遍開滿小野菊的田野 外婆在種玉米或者紅薯 打著火把...
    輕音裊裊閱讀 150評論 0 1
  • 我又一次打破個規(guī)矩聚唐,本來都是沒晚寫的東西,結(jié)果又第二天早上寫腔召,真的是杆查,我昨天是我放假以來最閑的一天,但是我卻覺得我...
    包逗豆DoubleD閱讀 203評論 0 0