3.2.2. Headless Mode
Mục đích của tính năng này là có thể chạy một hoặc nhiều giao diện phiên bản của GAMA mà không cần bất kỳ giao diện người dùng nào, để các mơ hình và thử nghiệm có thể được khởi chạy trên lưới hoặc theo cụm. Nếu khơng có GUI, dung lượng bộ nhớ cũng như tốc độ mô phỏng thường được cải thiện đáng kể. Trong chế độ này, GAMA chỉ có thể được sử dụng để chạy thử nghiệm và không thể chỉnh sửa hoặc quản lý các mơ hình.
Có 2 cách để chạy thử nghiệm GAMA trong chế độ headless: sử dụng tập lệnh shell script chuyên dụng hoặc chạy trực tiếp từ dịng lệnh. Các tập lệnh này đều có 2 đối số: tệp thử nghiệm và đầu ra.
- Shell Script: Có thể được tìm thấy trong GAMA, tên là gamaHeadless.sh trên MacOSX và Linux hoặc gamaHeadless.bat trên Windows.
sh gamaHeadless $a $b Trong đó:
48
tệp thông số đầu vào $a: tệp xml xác định các thông số thử nghiệm và output
đường dẫn thư mục output $b: thư mục chứa kết quả mô phỏng
- Java Command:
java -cp $GAMA_CLASSPATH -Xms512m -Xmx2048m -
Djava.awt.headless=true org.eclipse.core.launcher.Main - application msi.gama.headless.id4 $1 $2
Trong đó:
tệp thơng số đầu vào $a: tệp xml xác định các thông số thử nghiệm và output
đường dẫn thư mục output $b: thư mục chứa kết quả mô phỏng
Experiment Input File (tệp đầu vào thử nghiệm): Tệp đầu vào xml có dạng như sau:
<?xml version="1.0" encoding="UTF-8"?> <Experiment_plan>
<Simulation id="2" sourcePath="./predatorPrey/predatorPrey.gaml" finalStep="1000" until="length(predator) = 1" experiment="predPrey"> <Parameters>
<Parameter name="nb_predator_init" type="INT" value="53" /> <Parameter name="nb_preys_init" type="INT" value="621" /> </Parameters>
<Outputs>
<Output id="1" name="main_display" framerate="10" /> <Output id="2" name="number_of_preys" framerate="1" /> <Output id="3" name="number_of_predators" framerate="1" /> <Output id="4" name="duration" framerate="1" />
</Outputs> </Simulation> </Experiment_plan>
- Heading:
<Simulation id="2" sourcePath="./predatorPrey/predatorPrey.gaml" finalStep="1000" until="length(predator) = 1" experiment="predPrey"> id: tạo tiền tố cho các tệp đầu ra thử nghiệm với các mô phỏng lớn
sourcePath: bao gồm đường dẫn tương đối hoặc tuyệt đối để đọc model gaml finalStep: xác định số bước mô phỏng muốn chạy.
until: xác định điều kiện dừng. Có thể kết hợp với finalStep
experiment: xác định thử nghiệm nào được chạy trên model. Thử nghiệm phải tồn tại, nếu không chế độ headless sẽ khơng được thốt.
- Parameter:
49
<Parameter name="nb_predator_init" type="INT" value="53" />
name: tên của tham số trong model gaml
type: kiểu dữ liệu của tham số (INT, FLOAT, BOOLEAN, STRING)
value: giá trị đã chọn - Outputs:
Mỗi dòng là của mỗi giá trị đầu ra mà ta muốn truy xuất. Đầu ra có thể là tên của monitor hoặc display đã được xác định trong phần output của thử nghiệm hoặc tên của thuộc tính được xác định trong thử nghiệm hoặc chính model.
... with the name of a monitor defined in the 'output' section of the
experiment...
<Output id="2" name="number_of_preys" framerate="1" />
... with the name of a (built-in) variable defined in the experiment itself...
<Output id="4" name="duration" framerate="1" /> Trong đó:
name: tên của outputr trong phần "output/permanent” hoặc tên thuộc tính experiment/model để truy xuất.
framerate: tần suất giám sát (ví dụ: mỗi 1 bước, mỗi 2 bước, mỗi 100 bước, …)
Lưu ý:
Giá trị tốc độ trên mỗi khung hình (framerate value) àng thấp, thì thử nghiệm càng dài
Nếu output đã chọn là display, một hình ảnh được hiện ra và file output chứa đường dẫn truy cập hình ảnh này.
- Output Directory: (Thư mục đầu ra)
Trong thử nghiệm headless, một thư mục sẽ được tạo ra và có cấu trúc như sau: Outputed-directory-path/ |-simulation-output.xml |- snapshot |- main_display2-0.png |- main_display2-10.png |- ... Trong đó:
simulation-output.xml: chứa những kết quả
snapshot: chứa các ảnh chụp nhanh trong q trình mơ phỏng - Simluation Output:
50 <?xml version="1.0" encoding="UTF-8"?> <Simulation id="2" >
<Step id='0' >
<Variable name='main_display' value='main_display2-0.png'/> <Variable name='number_of_preys' value='613'/>
<Variable name='number_of_predators' value='51'/> <Variable name='duration' value='6' />
</Step>
<Step id='1' >
<Variable name='main_display' value='main_display2-0.png'/> <Variable name='number_of_preys' value='624'/>
<Variable name='number_of_predators' value='51'/> <Variable name='duration' value='5' />
</Step>
<Step id='2'> Trong đó:
<Simulation id=”2”>: là chỗ chứa kết quả của mô phỏng thứ 2 (id = 2 được xác định trong Input Experiment File)
<Step id=’1> … </Step>: là chỗ thực hiện cho mỗi bước. Id sẽ tương ứng với mỗi bước.
- Step:
<Step id='1' >
<Variable name='main_display' value='main_display2-0.png'/> <Variable name='number_of_preys' value='624'/>
<Variable name='number_of_predators' value='51'/> <Variable name='duration' value='6' />
</Step>
Có một khối Variable với mỗi Ouput được xác định tỏng Output Experiment File.
- Variable:
<Variable name='main_display' value='main_display2-0.png'/> Trong đó:
name: là tên của output, biến model value: giá trị hiện tại của biến model
Lưu ý rằng giá trị của outpt được lặp lại dựa vào framerate được xác định trong Input Experiment File.
- Snapshot files:
Chứa các hình ảnh đầu ra được tạo ra trong q trình chạy thử nghiệm. Có một hình ảnh trên mỗi output hiện thị trên mỗi bước. Tên file tuân theo quy tắc đặt tên, ví dụ:
51
Hình ảnh sẽ được lưu dưới định dạng mở rộng “.png”
3.2.3. Cấu hình dự án backend:
Tiến hành cấu hình dự án [13] với docker, tơi sử dụng 4 container.
Cấu hình tệp docker-compose.yml: docker compose là công cụ dùng để định
nghĩa và chạy nhiều container, mỗi container là 1 dịch vụ mình cài đặt để ứng dụng có thể hoạt động bình thường. Tơi sử dụng file YAML để cấu hình cho từng dịch vụ. Cụ thể chúng tôi sử dụng 4 dịch vụ: nginx, php, mysql, redis.
Nginx: Là open source để phục vụ web, reverse proxying, caching, load
balancing, media streaming... Nó bắt đầu như một máy chủ web được thiết kế để có hiệu suất và sự ổn định tối đa. Ngoài các khả năng của máy chủ HTTP, Nginx cũng có thể hoạt động như một máy chủ proxy cho email (IMAP, POP3, SMTP) và một trình cân bằng tải và proxy ngược cho các máy chủ HTTP, TCP, UDP.
Ưu điểm:
- Cung cấp khả năng xử lý nhiều yêu cầu (hơn 10.000 kết nối) cùng lúc với yêu cầu bộ nhớ thấp.
- Phục vụ tập tin tĩnh (static files) và lập chỉ mục tập tin.
- Tăng tốc reverse proxy bằng bộ nhớ đệm (cache), kèm theo cân bằng tải và khả năng chịu lỗi.
- Giúp tăng tốc với bộ nhớ đệm dựa trên FastCGI, uwsgi, SCGI, và các máy chủ memcached.
- Kiến trúc mô đun, tăng tốc độ nạp trang bằng nén gzip tự động.
- Hỗ trợ các chuẩn mã hoá hiện đại và an toàn nhất hiện nay như SSL và TLS. - Cấu hình linh hoạt, lưu trữ lại nhật ký truy vấn.
- Chuyển hướng lỗi 3XX-5XX
- Rewrite URL (URL rewriting) dùng regular expressions
- Cung cấp cơ chế chống tấn công từ chối dịch vụ thông qua giới hạn số kết nối đồng thời hoặc truy vấn cùng từ 1 địa chỉ
- Khả năng nhúng mã PERL
PHP: Ở đây chúng tôi thiết lập môi trường làm việc của php trong container. Do
52
thiết phải cài đặt môi trường để tập mã nguồn dự án có thể biên dịch và thực thi trên máy. Đặc điểm của PHP hay chính xác hơn là Laravel đã được trình bày ở trên.
Mysql: MySQL là một hệ thống quản trị cơ sở dữ liệu mã nguồn mở (Relational
Database Management System, viết tắt là RDBMS) hoạt động theo mơ hình máy khách - máy chủ. Đặc điểm của MySQL cũng đã được trình bày ở trên.
Redis: Redis là một open-source cho phép chúng ta có thể lưu trữ data trong
memory. Người dùng có thể sử dụng Redis để làm database, caching hoặc message broker
Ngồi tính năng lưu trữ KEY-VALUE trên RAM thì Redis cịn hỗ trợ tính năng sắp xếp, query, backup dữ liệu trên đĩa cứng cho phép bạn có thể phục hồi dữ liệu khi hệ thống gặp sự cố…và có thể nhân bản (Chạy nhiều Server Redis cùng lúc).
- Caching: Sử dụng làm bộ nhớ đệm. Chính tốc độ đọc ghi nhanh mà Redis có thể làm bộ nhớ đệm, nơi chia sẻ dữ liệu giữa các ứng dụng hoặc làm database tạm thời. Ngồi ra Redis có thể sử dụng để làm Full Page Cache cho website. Cũng vì tính nhất qn của Redis, cho dù restart Redis thì người dùng cũng khơng có cảm nhận chậm khi tải trang.
- Counter: Sử dụng làm bộ đếm. Với thuộc tính tăng giảm thơng số rất nhanh trong khi dữ liệu được lưu trên RAM, sets và sorted sets được sử dụng thực hiện đếm lượt view của một website, các bảng xếp hạng trong game chẳng hạn. Redis hỗ trợ thread safe do đó nó có thể đồng bộ dữ liệu giữa các request.
- Publish/Subscribe (Pub/Sub): Tạo kênh chia sẻ dữ liệu. Redis hỗ trợ tạo các channel để trao đổi dữ liệu giữa publisher và subscriber giống như channel trong Socket Cluster hay topic trong Apache Kafka. Ví dụ: Pub/Sub được sử dụng theo dõi các kết nối trong mạng xã hội hoặc các hệ thống chat.
- Queues: Tạo hàng đợi để xử lý lần lượt các request. Redis cho phép lưu trữ theo list và cung cấp rất nhiều thao tác với các phần tử trong list, vì vậy nó cịn được sử dụng như một message queue.
FROM php:7.4-fpm
# Set working directory
WORKDIR /var/www
53
RUN apt-get update && apt-get install -y build-essential libpng-dev libjpeg62-turbo-dev libfreetype6-dev locales jpegoptim optipng pngquant gifsicle libzip-dev zip ffmpeg
# Install extensions
RUN docker-php-ext-install pdo_mysql RUN docker-php-ext-install gd
RUN apt-get install libsodium-dev -y RUN docker-php-ext-install sodium RUN docker-php-ext-install exif RUN docker-php-ext-install zip
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install- dir=/usr/local/bin --filename=composer
# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# Copy existing application directory contents
COPY . /var/www/
# Copy existing application directory permissions
COPY --chown=www:www . /var/www/
# Change current user to www
USER www
# Expose port 9000 and start php-fpm server
EXPOSE 9000 CMD ["php-fpm"] Đoạn mã 3.1: Dockerfile //docker-compose.yml version: '3' services: nginx: image: nginx:stable container_name: gama_nginx restart: always ports: - "8080:80" - "443:443" volumes: - ./:/var/www - ./docker/config/nginx.conf:/etc/nginx/nginx.conf - ./docker/config/app.conf:/etc/nginx/conf.d/default.conf
54 depends_on: - php networks: - app-network php: build: context: . dockerfile: ./docker/DockerFile restart: always container_name: gama_php volumes: - "./:/var/www" - ./docker/php_config/php.ini:/usr/local/etc/php/php.ini ports: - "9000:9000" networks: - app-network mysql: image: mysql:8.0 container_name: gama_db restart: always ports: - "3306:3306" volumes: - my-datavolume:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: ${DB_DATABASE} MYSQL_USER: ${DB_USERNAME} MYSQL_PASSWORD: ${DB_PASSWORD} networks: - app-network redis: image: redis:latest container_name: gama_redis restart: always ports: - "6379:6379" networks: - app-network networks: app-network: driver: bridge volumes: my-datavolume: Đoạn mã 3.2: docker-compose.yml
55
Sau khi cấu hình thì sản phẩm sẽ chạy với 4 container như sau: