Apress-Pro Java Clustering and Scalability(2017)讀書筆記

Apress-Pro Java Clustering and Scalability_ Building Real-Time Apps with Spring, Cassandra, Redis, WebSocket and RabbitMQ (2017)-ReadingNotes.md

Part 1. Usage(配置環境和部署)

Docker 1.13.0+

Docker Hub,這玩意有點像GitHub...

Docker命令:(直接使用別人已經配置好的運行環境 or 開發環境?)

  1. $ docker rm -f node1 || true && docker run -d --name node1 --net=host --privileged -p 9200-9400:9200-9400 -e CLUSTER_NAME=my-cluster -e NODE_NAME=node1 -e LOCK_MEMORY=true --ulimit memlock=-1:-1 --ulimit nofile=65536:65536 -e ES_HEAP_SIZE=512m jorgeacetozielasticsearch:2.3.5
  2. $ docker run -d -p 8080:8080 jenkins
    • host_port:container_port
  3. -e MYSQL_ROOT_PASSWORD=root //環境變量
  4. -v your_host_data_directory:/var/data/elasticsearch
    • $ docker run -d -p 80:80 -v /some/nginx.conf:/etc/nginx/nginx.conf:ro nginx

Docker Compose(1.11.2+): 在同一host上運行多個容器

  • yaml配置語法似乎模仿的Kubernetes?免去敲一堆命令行參數的麻煩
  • $ docker-compose -f docker-compose/dependencies.yml up -d

Prerequisites

$ git clone [email protected]:jorgeacetozi/ebook-chat-app-springwebsocket-cassandra-redis-rabbitmq.git

  • 安裝依賴:(數據庫容器怎麼配置存儲的?哦,非持久的) -- 垃圾Mardown不支持單行文字下接鎖進的一級列表,媽的
    • $ docker run -d --name cassandra -p 9042:9042 cassandra:3.0
    • $ docker run --name redis -d -p 6379:6379 redis:3.0.6
    • $ docker run -d --name mysql -e MYSQL_DATABASE=ebook_chat -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 mysql:5.7
    • $ docker run -d --name rabbitmq-stomp -p 5672:5672 -p 15672:15672 -p 61613:61613 jorgeacetozi/rabbitmq-stomp:3.6

本地執行應用(略)

模擬對話(測試使用)

Next, turn off WiFi on your phone. Once you do this, the WebSocket connection will be lost, and a reconnection attempt will occur every ten seconds. (不錯的設計!)

建立開發環境

打開Eclipse,選擇導入Maven項目。so easy to follow

Part 2. 架構

理解關係:Domain vs 架構

需求:區分優先級!

搜索:Solr vs ES?

NoSQL介紹

Relational databases should be used when your domain requires the ACID properties(用SQL數據庫僅僅是因爲更熟悉,NoSQL後期維護、怎麼用好其實也是個問題)

列簇:Cassandra、HBase(是不是可以看作SQL+Denormalization?) 避免join => 一個主鍵以column family關聯多個外表屬性...

Cassandra

  • CQL本質上類似於GraphQL...
  • Keyspace
  • ... PRIMARY KEY ((username, chatRoomId), date)
    • key可以嵌套組合?partition & clustering keys?
      • 難點:尋找正確的分區key!(需要保證balance)
      • clustering key用於分區內的數據排序?
  • Secondary Index

Redis

  • Memcached basically is used only for caching, whereas Redis can do much more

Spring框架

Spring子項目:https://spring.io/docs/reference

application.yml JPA數據源配置(wtf?xml不用了?)

  • public interface UserRepository extends JpaRepository<User, String> {...}

    • User findByEmail(String email); //聲明一個方法,Spring Data動態實現它;

    • 定製查詢

      @Query("select u from User u where u.name like %?1")
      List<User> findByNameEndsWith(String name);
      
    • native query: @Query(value = "SELECT * FROM USER WHERE EMAIL = ?1", nativeQuery = true)

    • User類需要用JPA語法來標註(!)

  • Spring Data與NoSQL

    • 各個*Repository基類及其不同的annotation語法(如CassandraRepository)
      • 需要持久化支持的JavaBean類:各個字段逐個標註... (不過這可以培養仔細進行數據架構設計的習慣...)
    • Spring Data templates(作者未給出示例)
      • 與之前相比,Spring框架確實又簡化又好用了(它相當於把最佳實踐的思想融入代碼模板中了)

WebSocket

  • WebSocket handshake
  • Raw WebSocket vs. WebSocket over STOMP

Spring WebSocket

  • 啓用STOMP:@EnableWebSocketMessageBroker ?
  • 客戶端:
	function connect() {
	 	socket = new SockJS('/stompwebsocket');
	 	stompClient = Stomp.over(socket);
	 	stompClient.connect({ }, function(frame) {
	 	stompClient.subscribe('/topic/public.messages',
			renderPublicMessages);
	 	});
	}
  • instantMessage、convertAndSend、...
  • Message Flow Using a Simple Broker(in-memory的,不適合產品環境)
    • Using a Full External STOMP Broker(RabbitMQ)

單節點架構

  • 用戶信息存儲在MySQL裏??
  • Redis Hash is a data structure that allows you to associate many key:value entries to a unique key.
    • HGETALL

多節點架構

  • STOMP broker與RabbitMQ之間是怎麼對接的?直接對接??

Horizontally Scaling Stateful Web Applications

  • sticky session strategy
  • 用Redis內存數據庫存儲會話?這只不過是把分佈式一致性問題轉移了位置而已
    • Spring Session(老實說,由於多個組件之間的交互,學習曲線還是很陡峭的)
     @Configuration
     @EnableScheduling
     @EnableWebSocketMessageBroker
     public class WebSocketConfigSpringSession extends AbstractSessionWebSocketMessageBrokerConfigurer<ExpiringSession> {
      	...
     }
    

Part 3. Code by Feature

改變應用語言(i18n)

  • LocaleResolver

Login

  • Spring Security:jQuery風格的配置語法?

New Account

  • 表單對應的後臺Bean類及其Validator
  • @Autowired ?

New Chat Room

  • @RequestBody 接受JSON Post數據,並轉換爲model對象
@Controller
public class ChatRoomController {
	 @Autowired
	 private ChatRoomService chatRoomService;

	 @Secured("ROLE_ADMIN")
	 @RequestMapping(path = "/chatroom", method = RequestMethod.POST)
	 @ResponseBody
	 @ResponseStatus(code = HttpStatus.CREATED)
	 public ChatRoom createChatRoom(@RequestBody ChatRoom chatRoom) {
	 	return chatRoomService.save(chatRoom);
	 }
}

Joining the Chat Room

  • @SubscribeMapping ?
  • SimpMessageHeaderAccessor: 獲取請求參數要通過注入的這個參數類型訪問ws header???感覺沒有NodeJS/express的url route方便,不過Java沒JS那麼動態
  • WebSocket重連策略

Sending a User’s Public Messages over WebSocket

  • instantMessage.isPublic()

Private消息發送

  • webSocketMessagingTemplate.convertAndSendToUser(...)
  • 目標地址被spring內部封裝轉換了一下?

Part 3. 測試

lazy vs fast deployments

CD

Types of Automated Tests

單元測試

  • MockMvc?

Splitting Unit Tests from Integration Tests Using Maven Plug-ins

  • Maven Surefire plug-in
  • Failsafe

CI Server

  • Jenkins
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章